Skip to content
Open
Show file tree
Hide file tree
Changes from 57 commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
a1b0242
Clean up stdexec-only paths and update affected tests
guptapratykshh Mar 28, 2026
ed2e33b
fixed the formatting
guptapratykshh Mar 28, 2026
5f8cefd
fix stdexec clang-tidy and inspect build issues
guptapratykshh Mar 28, 2026
73b68db
fixed fetched stdexec target setup on Windows
guptapratykshh Mar 28, 2026
49c50da
fix stdexec API compatibility and modernization issues
guptapratykshh Mar 28, 2026
76377c0
revert dataflow lambda signatures to use future parameters
guptapratykshh Mar 29, 2026
b97d5c2
fix stdexec API compatibility for __operation and __promise templates
guptapratykshh Mar 29, 2026
d936bdf
Restore Hwloc dependency and check_required_components macro in HPXCo…
guptapratykshh Mar 29, 2026
3bd1359
Resolve bulk timeouts and formatting issues
guptapratykshh Mar 29, 2026
66cd010
clang-format 20 fixes on all modified files
guptapratykshh Mar 29, 2026
bccf525
workaround MSVC C2732 _mm_pause linkage conflict in stdexec stop_toke…
guptapratykshh Mar 29, 2026
7492415
fix C++ modules duplicate symbols, dataflow signatures, and sender_di…
guptapratykshh Mar 29, 2026
0566aad
Fix missing includes for inspect checks
guptapratykshh Mar 29, 2026
b95a1cd
Address maintainer feedback: delete hollowed files, revert orthogonal…
guptapratykshh Mar 30, 2026
15d36e9
execution: remove hollowed-out forwarding headers, modernize as_sender
guptapratykshh Mar 30, 2026
768590f
reverted some files
guptapratykshh Mar 30, 2026
6b06ea1
refactored hpx execution
guptapratykshh Mar 31, 2026
f4472b5
execution_base: include exec/completion_signatures.hpp
guptapratykshh Apr 1, 2026
8d573b2
execution_base: forward stdexec::get_domain and get_domain_t
guptapratykshh Apr 1, 2026
e7da440
suppress unused parameter warning in any_receiver
guptapratykshh Apr 1, 2026
b1e27f2
import HPX.Core in HPX.Full module to prevent duplicate symbols
guptapratykshh Apr 1, 2026
3c10404
pre-include <intrin.h> in module global fragment to fix MSVC C2732
guptapratykshh Apr 1, 2026
d209b3b
use continues_on instead of deprecated transfer in sender_diamond
guptapratykshh Apr 1, 2026
94bc3b1
resolve MSVC module linkage conflicts and synchronize P2300 pipelines
guptapratykshh Apr 1, 2026
7e49937
fix MSVC intrinsic linkage and Clang module purview violations
guptapratykshh Apr 1, 2026
b6b5e6d
Fix module build regressions
guptapratykshh Apr 1, 2026
4873e85
restore clean ixx.in structure, revert compiler_fence workaround
guptapratykshh Apr 1, 2026
c11b152
stdexec: fix module builds and transfer_just compatibility
guptapratykshh Apr 1, 2026
5fc985e
fix async_cuda completion signatures
guptapratykshh Apr 1, 2026
e494082
fix sender and async cuda compatibility
guptapratykshh Apr 2, 2026
574b5cd
Fix shift_left and shift_right task policy paths
guptapratykshh Apr 2, 2026
3027182
Fix executor deprecation warnings
guptapratykshh Apr 2, 2026
336b3ab
disable broken Clang stdexec tests
guptapratykshh Apr 3, 2026
728ec6e
skip timeout prone tests
guptapratykshh Apr 3, 2026
f753625
fix macos errors
guptapratykshh Apr 3, 2026
76865f1
Clean up stdexec paths and restore sender tests
guptapratykshh Apr 4, 2026
e23c9f8
Fix stdexec compatibility and formatting
guptapratykshh Apr 4, 2026
0f40e2a
Fix execution_base awaitable aliases
guptapratykshh Apr 5, 2026
fbfd7ce
Fix stdexec scheduler domain queries
guptapratykshh Apr 5, 2026
687b64f
Fix stdexec future dataflow dispatch
guptapratykshh Apr 5, 2026
1703aa6
Revert "Fix stdexec future dataflow dispatch"
guptapratykshh Apr 5, 2026
56d8e00
Remove HPX_HAVE_STDEXEC config define
guptapratykshh Apr 6, 2026
763afb4
Fix stdexec module symbol duplication
guptapratykshh Apr 6, 2026
92e0e59
cleanup: remove unrelated test tweaks
guptapratykshh Apr 7, 2026
5451901
Restore sender_diamond transfer usage
guptapratykshh Apr 8, 2026
764e826
Whitelist CMake endwhile keyword for codespell
guptapratykshh Apr 8, 2026
5b9a2d9
Use continues_on in sender_diamond
guptapratykshh Apr 9, 2026
57e2fe0
Keep sender_diamond on transfer
guptapratykshh Apr 9, 2026
aff8789
Disable sender_diamond test on Clang
guptapratykshh Apr 9, 2026
7b79039
Skip foreach_report on Clang
guptapratykshh Apr 10, 2026
98b3458
revert unrelated changes and fix Clang guard
guptapratykshh Apr 10, 2026
d3ee92d
pass executor to hpx::dataflow in sort and partial_sort
guptapratykshh Apr 12, 2026
11c9ade
exclude 1d_stencil_8 from Windows CI examples
guptapratykshh Apr 12, 2026
2ce2ba3
restore inline stdexec
guptapratykshh Apr 12, 2026
dddf55e
remove orphaned #endif in mismatch_tests.hpp
guptapratykshh Apr 16, 2026
59ce7b7
shift_right parallel path returns first+n and passes executor to data…
guptapratykshh Apr 16, 2026
a43f187
exclude transpose_smp_block from Windows CI due to stack overrun crash
guptapratykshh Apr 16, 2026
e3183de
move CI exclusions to exclude.targets and sort codespell whitelist
guptapratykshh Apr 17, 2026
32683b8
remove patches fixed upstream in NVIDIA/stdexec PR#2030
guptapratykshh Apr 19, 2026
8b4f6fc
remove stdexec::tags re-export (namespace removed from upstream stdexec)
guptapratykshh Apr 20, 2026
ff262f9
remove stdexec digit separator patching (fixed upstream in NVIDIA/std…
guptapratykshh Apr 21, 2026
9743342
revert unrelated changes, restore tests, add compiler versions
guptapratykshh Apr 21, 2026
98e25f3
set up Stdexec unconditionally
guptapratykshh Apr 22, 2026
8da4996
restore HPX_HAVE_STDEXEC define, bump foreach_report exclusion to App…
guptapratykshh Apr 22, 2026
68a1953
fix foreach_report exclusion to use VERSION_LESS to cover patch releases
guptapratykshh Apr 24, 2026
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
3 changes: 2 additions & 1 deletion .github/workflows/macos_debug_fetch_hwloc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ jobs:
cd build
ctest --output-on-failure \
--exclude-regex \
"tests.examples.transpose.transpose_block_numa|\
"tests.examples.quickstart.1d_wave_equation|\
tests.examples.transpose.transpose_block_numa|\
tests.performance.local.wait_all_timings|\
tests.regressions.modules.compute_local.parallel_fill_4132|\
tests.unit.modules.algorithms.default_construct|\
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/tests.examples.targets
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
#
tests.examples.1d_stencil.1d_stencil_6
tests.examples.1d_stencil.1d_stencil_7
tests.examples.1d_stencil.1d_stencil_8
tests.examples.transpose.transpose_smp_block
tests.examples.async_io.async_io_simple
tests.examples.modules.algorithms.run_on_all
tests.examples.modules.checkpoint.1d_stencil_4_checkpoint
Copy link
Copy Markdown
Contributor

@hkaiser hkaiser Apr 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this is a leftover file and should have been removed. If you want to exclude certain tests from the CI, please add those here: https://github.com/TheHPXProject/hpx/blob/master/.github/workflows/exclude.targets

Expand Down
15 changes: 14 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -623,11 +623,17 @@ hpx_option(

hpx_option(
HPX_WITH_STDEXEC BOOL
"Use STDEXEC executors instead of native HPX.(default: OFF)" OFF
"Use STDEXEC executors instead of native HPX.(default: ON)" ON
Comment thread
guptapratykshh marked this conversation as resolved.
Outdated
CATEGORY "Executor"
ADVANCED
)

if(NOT HPX_WITH_STDEXEC)
hpx_error(
"HPX_WITH_STDEXEC=OFF is no longer supported. HPX now requires stdexec."
)
endif()
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The option help text still suggests there are two supported modes (stdexec vs native), but the configuration now hard-errors when HPX_WITH_STDEXEC=OFF. Please update the option description to reflect that stdexec is required (or consider removing the option entirely if it is no longer a meaningful configuration knob).

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can remove the option altogether.


hpx_option(
HPX_WITH_FETCH_STDEXEC BOOL "Use FetchContent to fetch STDEXEC.(default: ON)"
ON
Expand Down Expand Up @@ -2065,6 +2071,13 @@ if(WIN32)
# Make sure that __cplusplus is properly defined
hpx_add_target_compile_option(-Zc:__cplusplus PUBLIC)

# stdexec requires the conforming MSVC preprocessor.
if(NOT (${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang"
AND "x${CMAKE_CXX_SIMULATE_ID}" STREQUAL "xMSVC")
)
hpx_add_target_compile_option(-Zc:preprocessor PUBLIC)
endif()

# Silence C++17 deprecation warnings
hpx_add_config_cond_define(_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS)

Expand Down
219 changes: 146 additions & 73 deletions cmake/HPX_SetupStdexec.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -10,83 +10,156 @@ if(STDEXEC_ROOT AND NOT Stdexec_ROOT)
unset(STDEXEC_ROOT CACHE)
endif()

if(HPX_WITH_STDEXEC)
# prefer HPX_WITH_FETCH_STDEXEC by default
if(Stdexec_ROOT AND HPX_WITH_FETCH_STDEXEC)
hpx_warn(
"Both Stdexec_ROOT and HPX_WITH_FETCH_STDEXEC are provided. HPX_WITH_FETCH_STDEXEC will take precedence."
if(Stdexec_ROOT AND HPX_WITH_FETCH_STDEXEC)
hpx_warn(
"Both Stdexec_ROOT and HPX_WITH_FETCH_STDEXEC are provided. HPX_WITH_FETCH_STDEXEC will take precedence."
)
endif()

function(_hpx_patch_stdexec_header header)
file(READ "${header}" _content)
set(_patched_content "${_content}")

# clang-scan-deps used for C++ modules currently rejects apostrophe-separated
# pp-number literals in stdexec. Remove digit separators in the fetched copy
# so dependency scanning succeeds.
set(_previous_content "")
while(NOT _patched_content STREQUAL _previous_content)
set(_previous_content "${_patched_content}")
string(REGEX REPLACE "([0-9])'([0-9])" "\\1\\2" _patched_content
"${_patched_content}"
)
endwhile()
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be changed in the upstream version Please create a PR for them.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed upstream in NVIDIA/stdexec PR #2035.


if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
# stdexec's stop_token header currently declares _mm_pause without the C
# linkage used by MSVC's intrinsic headers, which breaks module builds.
string(REPLACE "extern void _mm_pause();" "extern \"C\" void _mm_pause();"
_patched_content "${_patched_content}"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be fixed in the upstream version as well.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did you resolve this comment (and similar comments below)?

Copy link
Copy Markdown
Contributor Author

@guptapratykshh guptapratykshh Apr 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed upstream in NVIDIA/stdexec PR #2030.

)
endif()

hpx_add_config_define(HPX_HAVE_STDEXEC)
# C++20 module interface units can emit duplicate definitions for a few
# namespace-scope stdexec constants when both hpx_core and hpx_full consume
# the same headers. Mark them inline in the fetched copy so the module
# archives do not export strong duplicate symbols.
string(REPLACE "constexpr struct __catch_any_lvalue_t"
"inline constexpr struct __catch_any_lvalue_t"
_patched_content "${_patched_content}"
)
string(REPLACE "} __catch_any_lvalue{};" "} inline __catch_any_lvalue{};"
_patched_content "${_patched_content}"
)
string(REPLACE "constexpr __none_such __no_default{};"
"inline constexpr __none_such __no_default{};"
_patched_content "${_patched_content}"
)
string(REPLACE "constexpr std::size_t __npos = ~0UL;"
"inline constexpr std::size_t __npos = ~0UL;" _patched_content
"${_patched_content}"
)
string(REPLACE "constexpr char __type_name_prefix[] = \"__xyzzy<\";"
"inline constexpr char __type_name_prefix[] = \"__xyzzy<\";"
_patched_content "${_patched_content}"
)
string(REPLACE "constexpr char __type_name_suffix[] = \">::__plugh\";"
"inline constexpr char __type_name_suffix[] = \">::__plugh\";"
_patched_content "${_patched_content}"
)
string(REPLACE "constexpr auto __start_next_fn ="
"inline constexpr auto __start_next_fn =" _patched_content
"${_patched_content}"
)
string(REPLACE "constexpr size_t __default_buffer_size ="
"inline constexpr size_t __default_buffer_size ="
_patched_content "${_patched_content}"
)
string(REPLACE "constexpr char const *__pure_virt_msg ="
"inline constexpr char const *__pure_virt_msg ="
_patched_content "${_patched_content}"
)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This 'patching' is very brittle and will silently break if the source change. I think we should a) make the upstream accept this change, and b) find a better way of working around the issue you're facing.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed upstream in NVIDIA/stdexec PR #2030.


if(NOT _content STREQUAL _patched_content)
file(WRITE "${header}" "${_patched_content}")
endif()
endfunction()
Comment thread
guptapratykshh marked this conversation as resolved.
Outdated

function(_hpx_patch_stdexec_headers include_dir)
if(HPX_WITH_CXX_MODULES AND (CMAKE_CXX_COMPILER_ID STREQUAL "Clang"
OR CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
)
hpx_info("Patching stdexec headers for C++ modules dependency scanning")
file(GLOB_RECURSE stdexec_headers "${include_dir}/*.hpp")
foreach(stdexec_header IN LISTS stdexec_headers)
_hpx_patch_stdexec_header("${stdexec_header}")
endforeach()
endif()
endfunction()

if(HPX_WITH_FETCH_STDEXEC)
hpx_info(
"HPX_WITH_FETCH_STDEXEC=${HPX_WITH_FETCH_STDEXEC}, Stdexec will be fetched using CMake's FetchContent and installed alongside HPX (HPX_WITH_STDEXEC_TAG=${HPX_WITH_STDEXEC_TAG})"
)

include(FetchContent)
Comment thread
guptapratykshh marked this conversation as resolved.
fetchcontent_declare(
Stdexec
GIT_REPOSITORY https://github.com/NVIDIA/stdexec.git
GIT_TAG ${HPX_WITH_STDEXEC_TAG}
)

fetchcontent_getproperties(Stdexec)
if(NOT Stdexec_POPULATED)
fetchcontent_populate(Stdexec)
endif()
set(Stdexec_ROOT ${stdexec_SOURCE_DIR})
_hpx_patch_stdexec_headers("${stdexec_SOURCE_DIR}/include")

add_library(Stdexec INTERFACE)
target_include_directories(
Stdexec SYSTEM INTERFACE $<BUILD_INTERFACE:${stdexec_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
)

install(
TARGETS Stdexec
EXPORT HPXStdexecTarget
COMPONENT core
)

install(
DIRECTORY ${Stdexec_ROOT}/include/
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
COMPONENT core
FILES_MATCHING
PATTERN "*.hpp"
)

export(
TARGETS Stdexec
NAMESPACE Stdexec::
FILE "${CMAKE_CURRENT_BINARY_DIR}/lib/cmake/${HPX_PACKAGE_NAME}/HPXStdexecTarget.cmake"
)

install(
EXPORT HPXStdexecTarget
NAMESPACE Stdexec::
FILE HPXStdexecTarget.cmake
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${HPX_PACKAGE_NAME}
COMPONENT cmake
)

# TODO: Enforce a single spelling
add_library(Stdexec::Stdexec ALIAS Stdexec)
add_library(STDEXEC::stdexec ALIAS Stdexec)
else()
find_package(Stdexec)

if(HPX_WITH_FETCH_STDEXEC)
hpx_info(
"HPX_WITH_FETCH_STDEXEC=${HPX_WITH_FETCH_STDEXEC}, Stdexec will be fetched using CMake's FetchContent and installed alongside HPX (HPX_WITH_STDEXEC_TAG=${HPX_WITH_STDEXEC_TAG})"
if(NOT Stdexec_FOUND)
hpx_error(
"Stdexec could not be found, please specify Stdexec_ROOT to point to the correct location or enable HPX_WITH_FETCH_STDEXEC"
)
if(UNIX)
include(FetchContent)
fetchcontent_declare(
Stdexec
GIT_REPOSITORY https://github.com/NVIDIA/stdexec.git
GIT_TAG ${HPX_WITH_STDEXEC_TAG}
)

fetchcontent_getproperties(Stdexec)
if(NOT Stdexec_POPULATED)
fetchcontent_populate(Stdexec)
endif()
set(Stdexec_ROOT ${stdexec_SOURCE_DIR})

add_library(Stdexec INTERFACE)
target_include_directories(
Stdexec INTERFACE $<BUILD_INTERFACE:${stdexec_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
)

install(
TARGETS Stdexec
EXPORT HPXStdexecTarget
COMPONENT core
)

install(
DIRECTORY ${Stdexec_ROOT}/include/
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
COMPONENT core
FILES_MATCHING
PATTERN "*.hpp"
)

export(
TARGETS Stdexec
NAMESPACE Stdexec::
FILE "${CMAKE_CURRENT_BINARY_DIR}/lib/cmake/${HPX_PACKAGE_NAME}/HPXStdexecTarget.cmake"
)

install(
EXPORT HPXStdexecTarget
NAMESPACE Stdexec::
FILE HPXStdexecTarget.cmake
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${HPX_PACKAGE_NAME}
COMPONENT cmake
)

# TODO: Enforce a single spelling
add_library(Stdexec::Stdexec ALIAS Stdexec)
add_library(STDEXEC::stdexec ALIAS Stdexec)

endif()

else()
find_package(Stdexec)

if(Stdexec_FOUND)
hpx_add_config_define(HPX_HAVE_STDEXEC)
else()
hpx_error(
"Stdexec could not be found, please specify Stdexec_ROOT to point to the correct location or enable HPX_WITH_FETCH_STDEXEC"
)
endif()
elseif(Stdexec_INCLUDE_DIR)
_hpx_patch_stdexec_headers("${Stdexec_INCLUDE_DIR}")
Comment thread
guptapratykshh marked this conversation as resolved.
Outdated
endif()
endif()
10 changes: 4 additions & 6 deletions cmake/templates/std_headers.hpp.in
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
#include <hpx/config/modules_enabled.hpp>

@cxx_standard_headers@
#if defined(HPX_HAVE_STDEXEC)
# if defined(HPX_GCC_VERSION)
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wall"
Expand All @@ -32,7 +31,6 @@
# elif defined(HPX_CLANG_VERSION)
# pragma clang diagnostic pop
# endif
#endif

#if defined(HPX_HAVE_CXX20_COROUTINES)
# if defined(__has_include)
Expand All @@ -44,8 +42,8 @@
# endif
#endif

#include <bit>
#include <source_location>
# include <bit>
# include <source_location>

#if defined(HPX_HAVE_CXX23_STD_GENERATOR)
# include <generator>
Expand All @@ -60,8 +58,8 @@
# undef exception_info
#endif

#include <asio.hpp>
#include <hwloc.h>
# include <asio.hpp>
# include <hwloc.h>

#if defined(HPX_HAVE_MODULE_LIKWID)
# include <likwid.h>
Expand Down
3 changes: 3 additions & 0 deletions examples/quickstart/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,9 @@ set(disabled_tests error_handling fibonacci_await non_atomic_rma zerocopy_rdma)
if(HPX_WITH_STATIC_LINKING)
set(disabled_tests ${disabled_tests} hello_world_1)
endif()
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang|AppleClang")
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If disabling tests, please make sure to specify the latest compiler version that we know to fail. That will allow for the tests to be re-evaluated if a newer version will be available.

set(disabled_tests ${disabled_tests} sender_diamond)
endif()
if(HPX_WITH_DISTRIBUTED_RUNTIME)
set(disabled_tests ${disabled_tests} 1d_wave_equation)
endif()
Expand Down
16 changes: 16 additions & 0 deletions examples/quickstart/sender_diamond.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,16 @@ int hpx_main()

auto sched = ex::thread_pool_scheduler{};

// Keep the stable runtime behavior here and silence the local deprecation
// diagnostic so warning-as-error builds do not fail.
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
#elif defined(__GNUC__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#endif

// B. Double the value from A
auto b = a_shared | ex::transfer(sched) | ex::then([](int x) {
int result = x * 2;
Expand All @@ -57,6 +67,12 @@ int hpx_main()
return result;
});

#if defined(__clang__)
#pragma clang diagnostic pop
#elif defined(__GNUC__)
#pragma GCC diagnostic pop
#endif

// D. Join B and C, then sum their results
auto d = ex::then(
ex::when_all(std::move(b), std::move(c)), [](int from_b, int from_c) {
Expand Down
Loading
Loading