{"sha":"02512bcf94acd635f94849fd2dcc818d9bd79f50","node_id":"C_kwDOAiB0YNoAKDAyNTEyYmNmOTRhY2Q2MzVmOTQ4NDlmZDJkY2M4MThkOWJkNzlmNTA","commit":{"author":{"name":"gbottesi","email":"guillaume.bottesi@yahoo.fr","date":"2025-02-27T19:54:28Z"},"committer":{"name":"GitHub","email":"noreply@github.com","date":"2025-02-27T19:54:28Z"},"message":"No longer a header-only library. Added support for src files to make it simpler to integrate with dynamic libraries with hidden symbols.\n\nAdded .cpp files to hold thread pool and pre-exit support code to avoid duplicates when built as/in a DLL.\n\nDeclared pre_exit and at_pre_exit as extern \"C\" to make them simpler to export from a DLL in an export list.\n\nAdding an issue to make it simpler to export the default executor as well.\n\n---------\n\nCo-authored-by: Guillaume BOTTESI <bottesi@adobe.com>\nCo-authored-by: Sean Parent <sean.parent@stlab.cc>","tree":{"sha":"c778ca1df6c393a63dacf811575b2d7e70e293e4","url":"https://api.github.com/repos/stlab/stlab/git/trees/c778ca1df6c393a63dacf811575b2d7e70e293e4"},"url":"https://api.github.com/repos/stlab/stlab/git/commits/02512bcf94acd635f94849fd2dcc818d9bd79f50","comment_count":0,"verification":{"verified":true,"reason":"valid","signature":"-----BEGIN PGP SIGNATURE-----\n\nwsFcBAABCAAQBQJnwML0CRC1aQ7uu5UhlAAAVkcQAEUHUSedYVaqR3eXUycZsHf+\noo+kf2LVaP043UNTUf1zqdnIVYEHRMspzn/X+5IaPgx0phLis1GNMYGFt/E2mT2L\nCrYCc6yREl32f4HDhekXzwLFnWIgUGjtxj5W6006fJPUPBm/NA9HlG2gY4NHVj4Z\n7apAtK6xeRuvqYjD4SW8pDNaB8yQfU2fm070UTogFEbzv2REtF82orgHUz6rLXXN\nOWAKW5BQb7+VrioJ4Fw7s0ZRSFqxw1AVs+Czx0OwBL1vmJX3VbYwiVUFXjTSGNJm\n7YezjV2fci+rKRej3UX4hk1jXYlMi6gEFbpWoHsUDfuHI8xxDy758hGmOTpBlP/h\nWU7cPr9dtILeiX6mAO8SACzwGJnxmXtijeUOqcIEWguUha+aDe3qsrTVXiTpU7ZA\n3/J7dT2gNWV+3brDY3r6TeAPb/mXTEWfDEwyDHvLTXR0mG4n9IaSEf76WF1vQbqX\nYZmYHMliZ17WZ0+LhM8jHpGBbXgCfRx4afIrTBKh43xTrfzK9i7fuKOelKwnDkJk\nBoHcU/saXvVhdLbLqme+/sUkjVWLmWnA7/IzvUv2d2X87rICrXodhgoWs68/sm7D\nqY8i5oYSIB0AjYv/UlmSrHWIKb5XjKY1wi24U/iKovs62pGO8iarpVQ2VAL93jQn\nbswsnzCIDjCR6z5w3T0c\n=4ur+\n-----END PGP SIGNATURE-----\n","payload":"tree c778ca1df6c393a63dacf811575b2d7e70e293e4\nparent a97f0a39c740f204279ceccbb3ccc4f2f6102505\nauthor gbottesi <guillaume.bottesi@yahoo.fr> 1740686068 +0100\ncommitter GitHub <noreply@github.com> 1740686068 -0800\n\nNo longer a header-only library. Added support for src files to make it simpler to integrate with dynamic libraries with hidden symbols.\n\nAdded .cpp files to hold thread pool and pre-exit support code to avoid duplicates when built as/in a DLL.\n\nDeclared pre_exit and at_pre_exit as extern \"C\" to make them simpler to export from a DLL in an export list.\n\nAdding an issue to make it simpler to export the default executor as well.\n\n---------\n\nCo-authored-by: Guillaume BOTTESI <bottesi@adobe.com>\nCo-authored-by: Sean Parent <sean.parent@stlab.cc>","verified_at":"2025-02-27T19:59:30Z"}},"url":"https://api.github.com/repos/stlab/stlab/commits/02512bcf94acd635f94849fd2dcc818d9bd79f50","html_url":"https://github.com/stlab/stlab/commit/02512bcf94acd635f94849fd2dcc818d9bd79f50","comments_url":"https://api.github.com/repos/stlab/stlab/commits/02512bcf94acd635f94849fd2dcc818d9bd79f50/comments","author":{"login":"gbottesi","id":15667470,"node_id":"MDQ6VXNlcjE1NjY3NDcw","avatar_url":"https://avatars.githubusercontent.com/u/15667470?v=4","gravatar_id":"","url":"https://api.github.com/users/gbottesi","html_url":"https://github.com/gbottesi","followers_url":"https://api.github.com/users/gbottesi/followers","following_url":"https://api.github.com/users/gbottesi/following{/other_user}","gists_url":"https://api.github.com/users/gbottesi/gists{/gist_id}","starred_url":"https://api.github.com/users/gbottesi/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/gbottesi/subscriptions","organizations_url":"https://api.github.com/users/gbottesi/orgs","repos_url":"https://api.github.com/users/gbottesi/repos","events_url":"https://api.github.com/users/gbottesi/events{/privacy}","received_events_url":"https://api.github.com/users/gbottesi/received_events","type":"User","user_view_type":"public","site_admin":false},"committer":{"login":"web-flow","id":19864447,"node_id":"MDQ6VXNlcjE5ODY0NDQ3","avatar_url":"https://avatars.githubusercontent.com/u/19864447?v=4","gravatar_id":"","url":"https://api.github.com/users/web-flow","html_url":"https://github.com/web-flow","followers_url":"https://api.github.com/users/web-flow/followers","following_url":"https://api.github.com/users/web-flow/following{/other_user}","gists_url":"https://api.github.com/users/web-flow/gists{/gist_id}","starred_url":"https://api.github.com/users/web-flow/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/web-flow/subscriptions","organizations_url":"https://api.github.com/users/web-flow/orgs","repos_url":"https://api.github.com/users/web-flow/repos","events_url":"https://api.github.com/users/web-flow/events{/privacy}","received_events_url":"https://api.github.com/users/web-flow/received_events","type":"User","user_view_type":"public","site_admin":false},"parents":[{"sha":"a97f0a39c740f204279ceccbb3ccc4f2f6102505","url":"https://api.github.com/repos/stlab/stlab/commits/a97f0a39c740f204279ceccbb3ccc4f2f6102505","html_url":"https://github.com/stlab/stlab/commit/a97f0a39c740f204279ceccbb3ccc4f2f6102505"}],"stats":{"total":332,"additions":212,"deletions":120},"files":[{"sha":"7c6e6297e337c06a419235d9ded9f08a5a5d1ed6","filename":"CMakeLists.txt","status":"modified","additions":4,"deletions":19,"changes":23,"blob_url":"https://github.com/stlab/stlab/blob/02512bcf94acd635f94849fd2dcc818d9bd79f50/CMakeLists.txt","raw_url":"https://github.com/stlab/stlab/raw/02512bcf94acd635f94849fd2dcc818d9bd79f50/CMakeLists.txt","contents_url":"https://api.github.com/repos/stlab/stlab/contents/CMakeLists.txt?ref=02512bcf94acd635f94849fd2dcc818d9bd79f50","patch":"@@ -69,13 +69,7 @@ if((STLAB_MAIN_EXECUTOR STREQUAL \"qt6\") AND NOT Qt6Core_FOUND)\n   message(SEND_ERROR \"STLAB_MAIN_EXECUTOR is set to \\\"qt6\\\", but a Qt6 installation was not found.\")\n endif()\n \n-#\n-# stlab has no compiled components. As such, we declare it as an `INTERFACE`\n-# library, which denotes a collection of target propeties to be applied\n-# transitively to linking targets. In our case, this ammounts to an include\n-# directory, compile flags, linking flags, and links to system libraries.\n-#\n-add_library(stlab INTERFACE)\n+add_library(stlab)\n add_library(stlab::stlab ALIAS stlab)\n \n #\n@@ -84,8 +78,8 @@ add_library(stlab::stlab ALIAS stlab)\n # on how the configuration under which this library is being consumed.\n #\n target_include_directories(stlab INTERFACE\n-  $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>/include\n-  $<BUILD_INTERFACE:${PROJECT_BINARY_DIR}>/include\n+  $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>\n+  $<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/include>\n   $<INSTALL_INTERFACE:include>)\n \n #\n@@ -98,6 +92,7 @@ target_include_directories(stlab INTERFACE\n target_compile_definitions(stlab INTERFACE $<$<CXX_COMPILER_ID:MSVC>:NOMINMAX>)\n \n add_subdirectory(include/stlab)\n+add_subdirectory(src)\n \n if(NOT STLAB_THREAD_SYSTEM STREQUAL \"none\")\n   target_link_libraries(stlab INTERFACE Threads::Threads)\n@@ -130,16 +125,6 @@ write_basic_package_version_file(\n   VERSION ${stlab_VERSION}\n   COMPATIBILITY SameMajorVersion)\n \n-#\n-# As a header-only library, there are no target components to be installed\n-# directly (the PUBLIC_HEADER property is not white listed for INTERFACE\n-# targets for some reason).\n-#\n-# However, it is worthwhile export our target description in order to later\n-# generate a CMake configuration file for consumption by CMake's `find_package`\n-# intrinsic\n-#\n-\n install(\n   TARGETS stlab\n   EXPORT stlabTargets"},{"sha":"8daa270682bf282e6cfebb6e821aa2125489df56","filename":"CMakePresets.json","status":"modified","additions":3,"deletions":2,"changes":5,"blob_url":"https://github.com/stlab/stlab/blob/02512bcf94acd635f94849fd2dcc818d9bd79f50/CMakePresets.json","raw_url":"https://github.com/stlab/stlab/raw/02512bcf94acd635f94849fd2dcc818d9bd79f50/CMakePresets.json","contents_url":"https://api.github.com/repos/stlab/stlab/contents/CMakePresets.json?ref=02512bcf94acd635f94849fd2dcc818d9bd79f50","patch":"@@ -144,7 +144,8 @@\n             \"cacheVariables\": {\n                 \"CMAKE_CXX_STANDARD\": \"17\",\n                 \"CMAKE_BUILD_TYPE\": \"DEBUG\",\n-                \"CMAKE_CXX_INCLUDE_WHAT_YOU_USE\": \"include-what-you-use;-Xiwyu;--mapping_file=/usr/local/Cellar/include-what-you-use/0.23/libexec/share/include-what-you-use/boost-all.imp\"\n+                \"CMAKE_CXX_INCLUDE_WHAT_YOU_USE\":\n+                    \"include-what-you-use;-Xiwyu;--mapping_file=/usr/local/Cellar/include-what-you-use/0.23/libexec/share/include-what-you-use/boost-all.imp\"\n             }\n         }\n     ],\n@@ -170,7 +171,7 @@\n             \"description\": \"\",\n             \"displayName\": \"\",\n             \"configurePreset\": \"ninja-cpp20-debug-thread-undefined\",\n-            \"output\":{\n+            \"output\": {\n                 \"verbosity\": \"verbose\"\n             }\n         }"},{"sha":"dd4a4b42af068090b24e45aec38259c6b23daac2","filename":"docs/_data/contributors.json","status":"modified","additions":1,"deletions":1,"changes":2,"blob_url":"https://github.com/stlab/stlab/blob/02512bcf94acd635f94849fd2dcc818d9bd79f50/docs%2F_data%2Fcontributors.json","raw_url":"https://github.com/stlab/stlab/raw/02512bcf94acd635f94849fd2dcc818d9bd79f50/docs%2F_data%2Fcontributors.json","contents_url":"https://api.github.com/repos/stlab/stlab/contents/docs%2F_data%2Fcontributors.json?ref=02512bcf94acd635f94849fd2dcc818d9bd79f50","patch":"@@ -41,7 +41,7 @@\n         \"type\": \"User\",\n         \"user_view_type\": \"public\",\n         \"site_admin\": false,\n-        \"contributions\": 167\n+        \"contributions\": 170\n     },\n     {\n         \"login\": \"fosterbrereton\","},{"sha":"55dc6a335b9afdc16bc9562f3a84d5bba9e9806e","filename":"docs/include/stlab/pre_exit.hpp/f_at_pre_exit.md","status":"modified","additions":3,"deletions":3,"changes":6,"blob_url":"https://github.com/stlab/stlab/blob/02512bcf94acd635f94849fd2dcc818d9bd79f50/docs%2Finclude%2Fstlab%2Fpre_exit.hpp%2Ff_at_pre_exit.md","raw_url":"https://github.com/stlab/stlab/raw/02512bcf94acd635f94849fd2dcc818d9bd79f50/docs%2Finclude%2Fstlab%2Fpre_exit.hpp%2Ff_at_pre_exit.md","contents_url":"https://api.github.com/repos/stlab/stlab/contents/docs%2Finclude%2Fstlab%2Fpre_exit.hpp%2Ff_at_pre_exit.md?ref=02512bcf94acd635f94849fd2dcc818d9bd79f50","patch":"@@ -8,7 +8,7 @@ hyde:\n     - function\n   inline:\n     brief:\n-      - Register a pre-exit handler. The pre-exit-handler may not throw. With C++17 or later it is required to be `noexcept`.\n+      - Register a pre-exit handler. The `pre-exit-handler` may not throw. With C++17 or later it is required to be `noexcept`.\n   defined_in_file: stlab/pre_exit.hpp\n   overloads:\n     void at_pre_exit(stlab::pre_exit_handler):\n@@ -19,10 +19,10 @@ hyde:\n       description: Register the `pre_exit_handler` to be called on [`pre_exit()`](./f_pre_exit.html). The functions are called in the reverse order that they are registered.\n       inline:\n         description:\n-          - Register a pre-exit handler. The pre-exit-handler may not throw. With C++17 or later it is required to be `noexcept`.\n+          - Register a pre-exit handler. The `pre-exit-handler` may not throw. With C++17 or later it is required to be `noexcept`.\n       return: __OPTIONAL__\n       signature_with_names: void at_pre_exit(stlab::pre_exit_handler f)\n   namespace:\n     - stlab\n-    - v1\n+    - v2\n ---"},{"sha":"b884d6a6759a52f4a441b1ab0f4a70a9c50a57db","filename":"docs/include/stlab/pre_exit.hpp/f_pre_exit.md","status":"modified","additions":1,"deletions":1,"changes":2,"blob_url":"https://github.com/stlab/stlab/blob/02512bcf94acd635f94849fd2dcc818d9bd79f50/docs%2Finclude%2Fstlab%2Fpre_exit.hpp%2Ff_pre_exit.md","raw_url":"https://github.com/stlab/stlab/raw/02512bcf94acd635f94849fd2dcc818d9bd79f50/docs%2Finclude%2Fstlab%2Fpre_exit.hpp%2Ff_pre_exit.md","contents_url":"https://api.github.com/repos/stlab/stlab/contents/docs%2Finclude%2Fstlab%2Fpre_exit.hpp%2Ff_pre_exit.md?ref=02512bcf94acd635f94849fd2dcc818d9bd79f50","patch":"@@ -20,5 +20,5 @@ hyde:\n       signature_with_names: void pre_exit()\n   namespace:\n     - stlab\n-    - v1\n+    - v2\n ---"},{"sha":"2b956a7bd310cca253cc3da2d954cbc6f4f3b2b7","filename":"docs/include/stlab/pre_exit.hpp/f_stlab_at_pre_exit.md","status":"added","additions":28,"deletions":0,"changes":28,"blob_url":"https://github.com/stlab/stlab/blob/02512bcf94acd635f94849fd2dcc818d9bd79f50/docs%2Finclude%2Fstlab%2Fpre_exit.hpp%2Ff_stlab_at_pre_exit.md","raw_url":"https://github.com/stlab/stlab/raw/02512bcf94acd635f94849fd2dcc818d9bd79f50/docs%2Finclude%2Fstlab%2Fpre_exit.hpp%2Ff_stlab_at_pre_exit.md","contents_url":"https://api.github.com/repos/stlab/stlab/contents/docs%2Finclude%2Fstlab%2Fpre_exit.hpp%2Ff_stlab_at_pre_exit.md?ref=02512bcf94acd635f94849fd2dcc818d9bd79f50","patch":"@@ -0,0 +1,28 @@\n+---\n+layout: function\n+title: stlab_at_pre_exit\n+hyde:\n+  owner: __MISSING__\n+  brief: __INLINED__\n+  tags:\n+    - function\n+  inline:\n+    brief:\n+      - An `extern \"C\"` vector for `at_pre-exit()` to make it simpler to export the function from a shared library.\n+  defined_in_file: stlab/pre_exit.hpp\n+  overloads:\n+    void stlab_at_pre_exit(stlab::pre_exit_handler):\n+      arguments:\n+        - description: __OPTIONAL__\n+          name: f\n+          type: stlab::pre_exit_handler\n+      description: __INLINED__\n+      inline:\n+        description:\n+          - An `extern \"C\"` vector for `at_pre-exit()` to make it simpler to export the function from a shared library.\n+      return: __OPTIONAL__\n+      signature_with_names: void stlab_at_pre_exit(stlab::pre_exit_handler f)\n+  namespace:\n+    - stlab\n+    - v2\n+---"},{"sha":"a4030354cdce72046495d51e4f05bd7dd265d012","filename":"docs/include/stlab/pre_exit.hpp/f_stlab_pre_exit.md","status":"added","additions":24,"deletions":0,"changes":24,"blob_url":"https://github.com/stlab/stlab/blob/02512bcf94acd635f94849fd2dcc818d9bd79f50/docs%2Finclude%2Fstlab%2Fpre_exit.hpp%2Ff_stlab_pre_exit.md","raw_url":"https://github.com/stlab/stlab/raw/02512bcf94acd635f94849fd2dcc818d9bd79f50/docs%2Finclude%2Fstlab%2Fpre_exit.hpp%2Ff_stlab_pre_exit.md","contents_url":"https://api.github.com/repos/stlab/stlab/contents/docs%2Finclude%2Fstlab%2Fpre_exit.hpp%2Ff_stlab_pre_exit.md?ref=02512bcf94acd635f94849fd2dcc818d9bd79f50","patch":"@@ -0,0 +1,24 @@\n+---\n+layout: function\n+title: stlab_pre_exit\n+hyde:\n+  owner: __MISSING__\n+  brief: __INLINED__\n+  tags:\n+    - function\n+  inline:\n+    brief:\n+      - An `extern \"C\"` vector for `pre-exit()` to make it simpler to export the function from a shared library.\n+  defined_in_file: stlab/pre_exit.hpp\n+  overloads:\n+    void stlab_pre_exit():\n+      description: __INLINED__\n+      inline:\n+        description:\n+          - An `extern \"C\"` vector for `pre-exit()` to make it simpler to export the function from a shared library.\n+      return: __OPTIONAL__\n+      signature_with_names: void stlab_pre_exit()\n+  namespace:\n+    - stlab\n+    - v2\n+---"},{"sha":"ebe59d027c450e7359f908666056771c811b7828","filename":"docs/tools/docker-tools/README.md","status":"modified","additions":1,"deletions":1,"changes":2,"blob_url":"https://github.com/stlab/stlab/blob/02512bcf94acd635f94849fd2dcc818d9bd79f50/docs%2Ftools%2Fdocker-tools%2FREADME.md","raw_url":"https://github.com/stlab/stlab/raw/02512bcf94acd635f94849fd2dcc818d9bd79f50/docs%2Ftools%2Fdocker-tools%2FREADME.md","contents_url":"https://api.github.com/repos/stlab/stlab/contents/docs%2Ftools%2Fdocker-tools%2FREADME.md?ref=02512bcf94acd635f94849fd2dcc818d9bd79f50","patch":"@@ -75,7 +75,7 @@ This should leave you at a bash prompt that looks like this:\n app@fc7590a63ba3:~$\n ```\n \n-The hex number is the docker image container ID and may be different. Going foreward I refer to this as the _docker_ prompt to distinguish it from the _local_ prompt.\n+The hex number is the docker image container ID and may be different. Going foreword I refer to this as the _docker_ prompt to distinguish it from the _local_ prompt.\n \n ```\n cd /mnt/host"},{"sha":"aad10bb483d4f238b86fb58ab65065460d3dd174","filename":"include/stlab/CMakeLists.txt","status":"modified","additions":2,"deletions":2,"changes":4,"blob_url":"https://github.com/stlab/stlab/blob/02512bcf94acd635f94849fd2dcc818d9bd79f50/include%2Fstlab%2FCMakeLists.txt","raw_url":"https://github.com/stlab/stlab/raw/02512bcf94acd635f94849fd2dcc818d9bd79f50/include%2Fstlab%2FCMakeLists.txt","contents_url":"https://api.github.com/repos/stlab/stlab/contents/include%2Fstlab%2FCMakeLists.txt?ref=02512bcf94acd635f94849fd2dcc818d9bd79f50","patch":"@@ -44,7 +44,7 @@ stlab_generate_config_file()\n target_sources( stlab INTERFACE\n   FILE_SET stlab\n   TYPE HEADERS\n-  BASE_DIRS ${PROJECT_BINARY_DIR}\n+  BASE_DIRS ${PROJECT_BINARY_DIR}/include\n   FILES\n-    ${PROJECT_BINARY_DIR}/stlab/config.hpp\n+    ${PROJECT_BINARY_DIR}/include/stlab/config.hpp\n )"},{"sha":"a0772583e33e8783aa080197150e94fbaacb1b87","filename":"include/stlab/concurrency/default_executor.hpp","status":"modified","additions":7,"deletions":28,"changes":35,"blob_url":"https://github.com/stlab/stlab/blob/02512bcf94acd635f94849fd2dcc818d9bd79f50/include%2Fstlab%2Fconcurrency%2Fdefault_executor.hpp","raw_url":"https://github.com/stlab/stlab/raw/02512bcf94acd635f94849fd2dcc818d9bd79f50/include%2Fstlab%2Fconcurrency%2Fdefault_executor.hpp","contents_url":"https://api.github.com/repos/stlab/stlab/contents/include%2Fstlab%2Fconcurrency%2Fdefault_executor.hpp?ref=02512bcf94acd635f94849fd2dcc818d9bd79f50","patch":"@@ -11,25 +11,22 @@\n \n #include <stlab/config.hpp>\n \n-#include <stlab/pre_exit.hpp>\n-\n-#include <stlab/concurrency/set_current_thread_name.hpp>\n-#include <stlab/concurrency/task.hpp>\n-\n #include <cassert>\n-#include <chrono>\n #include <cstdint>\n-#include <functional>\n-#include <memory>\n #include <type_traits>\n #include <utility>\n \n #if STLAB_TASK_SYSTEM(LIBDISPATCH)\n #include <dispatch/dispatch.h>\n #elif STLAB_TASK_SYSTEM(WINDOWS)\n+#include <stlab/pre_exit.hpp>\n+\n #include <Windows.h>\n #include <memory>\n #elif STLAB_TASK_SYSTEM(PORTABLE)\n+#include <stlab/concurrency/set_current_thread_name.hpp>\n+#include <stlab/concurrency/task.hpp>\n+\n #include <algorithm>\n #include <atomic>\n #include <climits>\n@@ -79,17 +76,7 @@ struct group_t {\n     }\n };\n \n-inline auto group() -> group_t& {\n-    // Use an immediately executed lambda to atomically register pre-exit handler\n-    // and create the dispatch group.\n-    static group_t g{[] {\n-        at_pre_exit([]() noexcept { // <br>\n-            dispatch_group_wait(g._group, DISPATCH_TIME_FOREVER);\n-        });\n-        return group_t{};\n-    }()};\n-    return g;\n-}\n+group_t& group();\n \n template <executor_priority P = executor_priority::medium>\n struct executor_type {\n@@ -452,15 +439,7 @@ class priority_task_system {\n /// Returns an instance of the task system singleton. An immediately executed lambda is used\n /// to register the the task system for tear down pre-exit in a thread safe manner.\n \n-inline priority_task_system& pts() {\n-    // Uses the `nullptr` constructor with an immediate executed lambda to register the task\n-    // system in a thread safe manner.\n-    static priority_task_system only_task_system{[] {\n-        at_pre_exit([]() noexcept { only_task_system.join(); });\n-        return nullptr;\n-    }()};\n-    return only_task_system;\n-}\n+priority_task_system& pts();\n \n #endif\n "},{"sha":"7ff80d21a7bf1489a1a6c275753f44681db28be3","filename":"include/stlab/pre_exit.hpp","status":"modified","additions":11,"deletions":60,"changes":71,"blob_url":"https://github.com/stlab/stlab/blob/02512bcf94acd635f94849fd2dcc818d9bd79f50/include%2Fstlab%2Fpre_exit.hpp","raw_url":"https://github.com/stlab/stlab/raw/02512bcf94acd635f94849fd2dcc818d9bd79f50/include%2Fstlab%2Fpre_exit.hpp","contents_url":"https://api.github.com/repos/stlab/stlab/contents/include%2Fstlab%2Fpre_exit.hpp?ref=02512bcf94acd635f94849fd2dcc818d9bd79f50","patch":"@@ -10,16 +10,10 @@\n \n /**************************************************************************************************/\n \n-#include <cassert>\n-#include <mutex>\n-#include <vector>\n-\n-/**************************************************************************************************/\n-\n // The namespace for pre_exit cannot be changed without an ABI break. If making an ABI breaking\n // change in this file it needs to be done in a way supporting this version as well.\n namespace stlab {\n-inline namespace v1 {\n+inline namespace v2 {\n \n /**************************************************************************************************/\n \n@@ -30,68 +24,25 @@ using pre_exit_handler = void (*)() noexcept;\n using pre_exit_handler = void (*)();\n #endif\n \n-namespace detail {\n-\n-/// Thread-safe stack of pre-exit handlers. The stack closes after the last element is popped.\n-struct _pre_exit_stack_t {\n-    using lock_t = std::unique_lock<std::mutex>;\n-\n-    std::mutex _mutex;\n-    std::vector<pre_exit_handler> _stack;\n-    bool _closed{false};\n-\n-    /// Push an exit handler. Precondition that stack is not closed.\n-    void push(pre_exit_handler f) {\n-        lock_t lock{_mutex};\n-        assert(\n-            !_closed &&\n-            \"WARNING: Adding pre-exit handler with `at_pre_exit()` after `pre_exit()` completed.\");\n-        _stack.push_back(f);\n-    }\n-\n-    /// Pop one exit handler, returns `nullptr` and closes stack if empty.\n-    auto pop() -> pre_exit_handler {\n-        lock_t lock{_mutex};\n-        if (_stack.empty()) {\n-            assert(!_closed && \"WARNING `pre_exit()` invoked more than once.\");\n-            _closed = true;\n-            return nullptr;\n-        }\n-        auto result = _stack.back();\n-        _stack.pop_back();\n-        return result;\n-    }\n-\n-    ~_pre_exit_stack_t() {\n-        assert(_closed && \"WARNING: `pre_exit()` not called before program exit.\");\n-    }\n-};\n-\n-/// Returns a reference to the pre-exit stack singleton.\n-inline auto _pre_exit_stack() -> auto& {\n-    static _pre_exit_stack_t _q;\n-    return _q;\n-}\n-\n-} // namespace detail\n+/// An `extern \"C\"` vector for `pre-exit()` to make it simpler to\n+/// export the function from a shared library.\n+extern \"C\" void stlab_pre_exit();\n+/// An `extern \"C\"` vector for `at_pre-exit()` to make it simpler to\n+/// export the function from a shared library.\n+extern \"C\" void stlab_at_pre_exit(pre_exit_handler f);\n \n /// Invoke all registered pre-exit handlers in the reverse order they are registered. It is safe\n /// to register additional handlers during this operation. Must be invoked exactly once prior to\n /// program exit.\n-inline void pre_exit() {\n-    auto& _s = detail::_pre_exit_stack();\n-    while (auto f = _s.pop()) {\n-        f();\n-    };\n-}\n+inline void pre_exit() { stlab_pre_exit(); }\n \n-/// Register a pre-exit handler. The pre-exit-handler may not throw. With C++17 or later it\n+/// Register a pre-exit handler. The `pre-exit-handler` may not throw. With C++17 or later it\n /// is required to be `noexcept`.\n-inline void at_pre_exit(pre_exit_handler f) { detail::_pre_exit_stack().push(f); }\n+inline void at_pre_exit(pre_exit_handler f) { stlab_at_pre_exit(f); }\n \n /**************************************************************************************************/\n \n-} // namespace v1\n+} // namespace v2\n } // namespace stlab\n \n /**************************************************************************************************/"},{"sha":"1fd406953afd2b6b24d2685ce58ceefffadd8081","filename":"include/stlab/utility.hpp","status":"modified","additions":5,"deletions":3,"changes":8,"blob_url":"https://github.com/stlab/stlab/blob/02512bcf94acd635f94849fd2dcc818d9bd79f50/include%2Fstlab%2Futility.hpp","raw_url":"https://github.com/stlab/stlab/raw/02512bcf94acd635f94849fd2dcc818d9bd79f50/include%2Fstlab%2Futility.hpp","contents_url":"https://api.github.com/repos/stlab/stlab/contents/include%2Fstlab%2Futility.hpp?ref=02512bcf94acd635f94849fd2dcc818d9bd79f50","patch":"@@ -14,7 +14,10 @@\n #include <stlab/config.hpp>\n \n #include <array>\n-#include <type_traits>\n+#include <cstddef>          // for size_t\n+#include <initializer_list> // for initializer_list\n+#include <type_traits>      // for remove_reference, is_same, is_const\n+#include <utility>          // for index_sequence, forward\n \n /**************************************************************************************************/\n \n@@ -76,8 +79,7 @@ template <class Seq, template <std::size_t> class F, std::size_t Index, std::siz\n struct index_sequence_transform;\n \n template <class Seq,\n-          template <std::size_t>\n-          class F,\n+          template <std::size_t> class F,\n           std::size_t Index = 0,\n           std::size_t Count = Seq::size()>\n using index_sequence_transform_t = typename index_sequence_transform<Seq, F, Index, Count>::type;"},{"sha":"609999893baa8c217529444a00f4b77ac9a19a06","filename":"src/CMakeLists.txt","status":"added","additions":7,"deletions":0,"changes":7,"blob_url":"https://github.com/stlab/stlab/blob/02512bcf94acd635f94849fd2dcc818d9bd79f50/src%2FCMakeLists.txt","raw_url":"https://github.com/stlab/stlab/raw/02512bcf94acd635f94849fd2dcc818d9bd79f50/src%2FCMakeLists.txt","contents_url":"https://api.github.com/repos/stlab/stlab/contents/src%2FCMakeLists.txt?ref=02512bcf94acd635f94849fd2dcc818d9bd79f50","patch":"@@ -0,0 +1,7 @@\n+target_sources(stlab PRIVATE pre_exit.cpp concurrency/default_executor.cpp)\n+target_include_directories(stlab PRIVATE ${CMAKE_SOURCE_DIR}/include ${CMAKE_BINARY_DIR}/include)\n+target_compile_definitions(stlab PRIVATE $<$<CXX_COMPILER_ID:MSVC>:NOMINMAX>)\n+\n+if(BUILD_SHARED_LIBS)\n+    set_target_properties(stlab PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON)\n+endif()"},{"sha":"2b3ca0170980cf9a94410dd479b3ccdbd179f248","filename":"src/concurrency/default_executor.cpp","status":"added","additions":45,"deletions":0,"changes":45,"blob_url":"https://github.com/stlab/stlab/blob/02512bcf94acd635f94849fd2dcc818d9bd79f50/src%2Fconcurrency%2Fdefault_executor.cpp","raw_url":"https://github.com/stlab/stlab/raw/02512bcf94acd635f94849fd2dcc818d9bd79f50/src%2Fconcurrency%2Fdefault_executor.cpp","contents_url":"https://api.github.com/repos/stlab/stlab/contents/src%2Fconcurrency%2Fdefault_executor.cpp?ref=02512bcf94acd635f94849fd2dcc818d9bd79f50","patch":"@@ -0,0 +1,45 @@\n+/*\n+    Copyright 2025 Adobe\n+    Distributed under the Boost Software License, Version 1.0.\n+    (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\n+*/\n+\n+/**************************************************************************************************/\n+\n+#include <stlab/concurrency/default_executor.hpp>\n+\n+#include \"stlab/config.hpp\" // for STLAB_TASK_SYSTEM, STLAB_TASK_SYSTEM_L...\n+\n+#include \"stlab/pre_exit.hpp\" // for at_pre_exit\n+\n+namespace stlab {\n+inline namespace STLAB_VERSION_NAMESPACE() {\n+namespace detail {\n+\n+#if STLAB_TASK_SYSTEM(LIBDISPATCH)\n+group_t& group() {\n+    // Use an immediately executed lambda to atomically register pre-exit handler\n+    // and create the dispatch group.\n+    static group_t g{[] {\n+        at_pre_exit([]() noexcept { // <br>\n+            dispatch_group_wait(g._group, DISPATCH_TIME_FOREVER);\n+        });\n+        return group_t{};\n+    }()};\n+    return g;\n+}\n+#elif STLAB_TASK_SYSTEM(PORTABLE)\n+priority_task_system& pts() {\n+    // Uses the `nullptr` constructor with an immediate executed lambda to register the task\n+    // system in a thread safe manner.\n+    static priority_task_system only_task_system{[] {\n+        at_pre_exit([]() noexcept { only_task_system.join(); });\n+        return nullptr;\n+    }()};\n+    return only_task_system;\n+}\n+#endif\n+\n+} // namespace detail\n+} // namespace STLAB_VERSION_NAMESPACE()\n+} // namespace stlab"},{"sha":"e0f255e33d61b0a49a9c89a27a5474470c85890c","filename":"src/pre_exit.cpp","status":"added","additions":70,"deletions":0,"changes":70,"blob_url":"https://github.com/stlab/stlab/blob/02512bcf94acd635f94849fd2dcc818d9bd79f50/src%2Fpre_exit.cpp","raw_url":"https://github.com/stlab/stlab/raw/02512bcf94acd635f94849fd2dcc818d9bd79f50/src%2Fpre_exit.cpp","contents_url":"https://api.github.com/repos/stlab/stlab/contents/src%2Fpre_exit.cpp?ref=02512bcf94acd635f94849fd2dcc818d9bd79f50","patch":"@@ -0,0 +1,70 @@\n+/*\n+    Copyright 2025 Adobe\n+    Distributed under the Boost Software License, Version 1.0.\n+    (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\n+*/\n+/**************************************************************************************************/\n+\n+#include <stlab/pre_exit.hpp>\n+\n+#include <cassert>\n+#include <mutex>\n+#include <vector>\n+\n+namespace stlab {\n+inline namespace v2 {\n+\n+namespace {\n+\n+struct pre_exit_stack_t {\n+    using lock_t = std::unique_lock<std::mutex>;\n+\n+    std::mutex _mutex;\n+    std::vector<pre_exit_handler> _stack;\n+    bool _closed{false};\n+\n+    /// Push an exit handler. Precondition that stack is not closed.\n+    void push(pre_exit_handler f) {\n+        lock_t lock{_mutex};\n+        assert(\n+            !_closed &&\n+            \"WARNING: Adding pre-exit handler with `at_pre_exit()` after `pre_exit()` completed.\");\n+        _stack.push_back(f);\n+    }\n+\n+    /// Pop one exit handler, returns `nullptr` and closes stack if empty.\n+    auto pop() -> pre_exit_handler {\n+        lock_t lock{_mutex};\n+        if (_stack.empty()) {\n+            assert(!_closed && \"WARNING `pre_exit()` invoked more than once.\");\n+            _closed = true;\n+            return nullptr;\n+        }\n+        auto result = _stack.back();\n+        _stack.pop_back();\n+        return result;\n+    }\n+\n+    ~pre_exit_stack_t() {\n+        assert(_closed && \"WARNING: `pre_exit()` not called before program exit.\");\n+    }\n+};\n+\n+auto pre_exit_stack() -> auto& {\n+    static pre_exit_stack_t _q;\n+    return _q;\n+}\n+\n+} // namespace\n+\n+extern \"C\" void stlab_pre_exit() {\n+    auto& _s = pre_exit_stack();\n+    while (auto f = _s.pop()) {\n+        f();\n+    };\n+}\n+\n+extern \"C\" void stlab_at_pre_exit(pre_exit_handler f) { pre_exit_stack().push(f); }\n+\n+} // namespace v2\n+} // namespace stlab"}]}