Skip to content

Commit a72ea6c

Browse files
committed
Enhance thread handling and error management in nt and win32 headers
- Updated `RtlCreateUserThread` signature to accept a function pointer for improved flexibility. - Refined error handling in thread creation and management functions to ensure proper resource cleanup on failure. - Standardized the use of `inline constexpr` for thread-related functions to enhance performance and clarity. - Improved sleep functions to validate input parameters and handle edge cases more effectively. - Streamlined namespace usage and organization for better code maintainability.
1 parent 81f7d3c commit a72ea6c

File tree

3 files changed

+267
-56
lines changed

3 files changed

+267
-56
lines changed

include/fast_io_hosted/platforms/nt/nt_api.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ FAST_IO_DLLIMPORT void FAST_IO_WINSTDCALL RtlEnterCriticalSection(void *) noexce
4545
FAST_IO_DLLIMPORT int FAST_IO_WINSTDCALL RtlTryEnterCriticalSection(void *) noexcept FAST_IO_WINSTDCALL_RENAME(RtlTryEnterCriticalSection, 4);
4646
FAST_IO_DLLIMPORT void FAST_IO_WINSTDCALL RtlLeaveCriticalSection(void *) noexcept FAST_IO_WINSTDCALL_RENAME(RtlLeaveCriticalSection, 4);
4747
FAST_IO_DLLIMPORT void FAST_IO_WINSTDCALL RtlDeleteCriticalSection(void *) noexcept FAST_IO_WINSTDCALL_RENAME(RtlDeleteCriticalSection, 4);
48-
FAST_IO_DLLIMPORT ::std::uint_least32_t FAST_IO_WINSTDCALL RtlCreateUserThread(void *, void *, int, ::std::uint_least32_t, ::std::size_t, ::std::size_t, void *, void *, void **, ::fast_io::win32::nt::client_id *) noexcept FAST_IO_WINSTDCALL_RENAME(RtlCreateUserThread, 40);
48+
FAST_IO_DLLIMPORT ::std::uint_least32_t FAST_IO_WINSTDCALL RtlCreateUserThread(void *, void *, int, ::std::uint_least32_t, ::std::size_t, ::std::size_t, ::std::uint_least32_t (FAST_IO_WINSTDCALL*)(void*), void *, void **, ::fast_io::win32::nt::client_id *) noexcept FAST_IO_WINSTDCALL_RENAME(RtlCreateUserThread, 40);
4949
FAST_IO_DLLIMPORT ::std::uint_least32_t FAST_IO_WINSTDCALL NtResumeThread(void *, ::std::uint_least32_t *) noexcept FAST_IO_WINSTDCALL_RENAME(NtResumeThread, 8);
5050
FAST_IO_DLLIMPORT ::std::uint_least32_t FAST_IO_WINSTDCALL ZwResumeThread(void *, ::std::uint_least32_t *) noexcept FAST_IO_WINSTDCALL_RENAME(ZwResumeThread, 8);
5151
FAST_IO_DLLIMPORT ::std::uint_least32_t FAST_IO_WINSTDCALL NtLockFile(void *, void *, ::fast_io::win32::nt::pio_apc_routine, void *, ::fast_io::win32::nt::io_status_block *, ::std::int_least64_t *, ::std::int_least64_t *, ::std::uint_least32_t, char unsigned, char unsigned) noexcept FAST_IO_WINSTDCALL_RENAME(NtLockFile, 40);

include/fast_io_hosted/threads/thread/nt.h

Lines changed: 74 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,23 @@ class nt_thread_start_routine_tuple_allocate_guard
4343
};
4444

4545
template <typename Tuple, ::std::size_t... Is>
46-
inline constexpr ::std::uint_least32_t FAST_IO_WINSTDCALL thread_start_routine(void *args) noexcept(noexcept(
47-
::std::invoke(::fast_io::get<Is>(*reinterpret_cast<Tuple *>(args))...)))
46+
inline constexpr ::std::uint_least32_t FAST_IO_WINSTDCALL thread_start_routine(void *args) noexcept
4847
{
4948
[[maybe_unused]] ::fast_io::win32::nt::details::nt_thread_start_routine_tuple_allocate_guard<Tuple> _(args);
50-
::std::invoke(::fast_io::get<Is>(*reinterpret_cast<Tuple *>(args))...);
49+
50+
#ifdef FAST_IO_CPP_EXCEPTIONS
51+
try
52+
#endif
53+
{
54+
::std::invoke(::fast_io::get<Is>(*reinterpret_cast<Tuple *>(args))...);
55+
}
56+
#ifdef FAST_IO_CPP_EXCEPTIONS
57+
catch (...)
58+
{
59+
::fast_io::fast_terminate();
60+
}
61+
#endif
62+
5163
return 0;
5264
}
5365

@@ -101,14 +113,20 @@ class nt_thread
101113
0, // StackZeroBits
102114
0, // StackReserved
103115
0, // StackCommit
104-
reinterpret_cast<void *>(start_routine),
116+
start_routine,
105117
start_routine_tuple, // args of func
106118
__builtin_addressof(this->handle_),
107119
__builtin_addressof(cid))};
120+
108121
if (status) [[unlikely]]
109122
{
123+
// Creation failed; manual release is required.
124+
::std::ranges::destroy_at(reinterpret_cast<start_routine_tuple_type *>(start_routine_tuple));
125+
::fast_io::generic_allocator_adapter<::fast_io::nt_rtlallocateheap_allocator>::deallocate(start_routine_tuple);
126+
110127
::fast_io::throw_nt_error(status);
111128
}
129+
112130
this->id_ = cid.UniqueThread;
113131
}
114132

@@ -159,6 +177,12 @@ class nt_thread
159177
{
160178
::fast_io::throw_nt_error(status);
161179
}
180+
status = ::fast_io::win32::nt::nt_close<zw>(this->handle_);
181+
if (status) [[unlikely]]
182+
{
183+
::fast_io::throw_nt_error(status);
184+
}
185+
this->handle_ = nullptr;
162186
this->id_ = nullptr;
163187
}
164188

@@ -211,7 +235,7 @@ class nt_thread
211235
::fast_io::throw_nt_error(status);
212236
}
213237

214-
return reinterpret_cast<::std::uint_least32_t>(tbi.ClientId.UniqueThread);
238+
return static_cast<::std::uint_least32_t>(reinterpret_cast<::std::size_t>(tbi.ClientId.UniqueThread));
215239
}
216240

217241
inline static constexpr ::std::uint_least32_t hardware_concurrency()
@@ -231,7 +255,13 @@ namespace this_thread
231255
{
232256

233257
template <bool zw = false>
234-
inline constexpr ::fast_io::win32::nt::nt_thread<zw>::id get_id()
258+
inline
259+
#if __cpp_constexpr >= 202207L
260+
// https://en.cppreference.com/w/cpp/compiler_support/23.html#cpp_constexpr_202207L
261+
// for reduce some warning purpose
262+
constexpr
263+
#endif
264+
::fast_io::win32::nt::nt_thread<zw>::id get_id()
235265
{
236266
::fast_io::win32::nt::thread_basic_information tbi;
237267
::std::uint_least32_t status{::fast_io::win32::nt::nt_query_information_thread<zw>(
@@ -247,18 +277,30 @@ inline constexpr ::fast_io::win32::nt::nt_thread<zw>::id get_id()
247277
return tbi.ClientId.UniqueThread;
248278
}
249279

250-
inline ::std::uint_least32_t get_win32_id() noexcept
280+
inline
281+
#if __cpp_constexpr >= 202207L
282+
// https://en.cppreference.com/w/cpp/compiler_support/23.html#cpp_constexpr_202207L
283+
// for reduce some warning purpose
284+
constexpr
285+
#endif
286+
::std::uint_least32_t get_win32_id() noexcept
251287
{
252288
auto teb{::fast_io::win32::nt::nt_current_teb()};
253289
return static_cast<::std::uint_least32_t>(reinterpret_cast<::std::size_t>(teb->ClientId.UniqueThread));
254290
}
255291

256292
template <bool zw = false, typename Rep, typename Period>
257-
inline constexpr void sleep_for(::std::chrono::duration<Rep, Period> const &sleep_duration)
293+
inline
294+
#if __cpp_constexpr >= 202207L
295+
// https://en.cppreference.com/w/cpp/compiler_support/23.html#cpp_constexpr_202207L
296+
// for reduce some warning purpose
297+
constexpr
298+
#endif
299+
void sleep_for(::std::chrono::duration<Rep, Period> const &sleep_duration)
258300
{
259-
auto const count{
301+
auto const count{static_cast<::std::uint_least64_t>(
260302
::std::chrono::duration_cast<::std::chrono::microseconds>(sleep_duration).count() * 10u +
261-
::std::chrono::duration_cast<::std::chrono::nanoseconds>(sleep_duration).count() / 100u % 10u};
303+
::std::chrono::duration_cast<::std::chrono::nanoseconds>(sleep_duration).count() / 100u % 10u)};
262304

263305
if (count > static_cast<::std::uint_least64_t>(::std::numeric_limits<::std::int_least64_t>::max()))
264306
{
@@ -274,7 +316,13 @@ inline constexpr void sleep_for(::std::chrono::duration<Rep, Period> const &slee
274316
}
275317

276318
template <bool zw = false, ::std::int_least64_t off_to_epoch>
277-
inline constexpr void sleep_for(::fast_io::basic_timestamp<off_to_epoch> const &sleep_duration)
319+
inline
320+
#if __cpp_constexpr >= 202207L
321+
// https://en.cppreference.com/w/cpp/compiler_support/23.html#cpp_constexpr_202207L
322+
// for reduce some warning purpose
323+
constexpr
324+
#endif
325+
void sleep_for(::fast_io::basic_timestamp<off_to_epoch> const &sleep_duration)
278326
{
279327
if (sleep_duration.seconds < 0) [[unlikely]]
280328
{
@@ -297,7 +345,13 @@ inline constexpr void sleep_for(::fast_io::basic_timestamp<off_to_epoch> const &
297345
}
298346

299347
template <bool zw = false, typename Clock, typename Duration>
300-
inline constexpr void sleep_until(::std::chrono::time_point<Clock, Duration> const &expect_time)
348+
inline
349+
#if __cpp_constexpr >= 202207L
350+
// https://en.cppreference.com/w/cpp/compiler_support/23.html#cpp_constexpr_202207L
351+
// for reduce some warning purpose
352+
constexpr
353+
#endif
354+
void sleep_until(::std::chrono::time_point<Clock, Duration> const &expect_time)
301355
{
302356
auto const unix_ts = ::std::chrono::duration_cast<std::chrono::seconds>(
303357
expect_time.time_since_epoch())
@@ -329,7 +383,13 @@ inline constexpr void sleep_until(::std::chrono::time_point<Clock, Duration> con
329383
}
330384

331385
template <bool zw = false, ::std::int_least64_t off_to_epoch>
332-
inline constexpr void sleep_until(::fast_io::basic_timestamp<off_to_epoch> const &expect_time)
386+
inline
387+
#if __cpp_constexpr >= 202207L
388+
// https://en.cppreference.com/w/cpp/compiler_support/23.html#cpp_constexpr_202207L
389+
// for reduce some warning purpose
390+
constexpr
391+
#endif
392+
void sleep_until(::fast_io::basic_timestamp<off_to_epoch> const &expect_time)
333393
{
334394
if (expect_time.seconds < 0) [[unlikely]]
335395
{
@@ -360,7 +420,7 @@ inline constexpr void sleep_until(::fast_io::basic_timestamp<off_to_epoch> const
360420
using nt_thread = win32::nt::nt_thread<false>;
361421
using zw_thread = win32::nt::nt_thread<true>;
362422

363-
#if defined(_WIN32) && !defined(_WIN32_WINDOWS)
423+
#if ((defined(_WIN32) && !defined(__WINE__)) && !defined(__CYGWIN__)) && !defined(_WIN32_WINDOWS)
364424
using native_thread = nt_thread;
365425

366426
namespace this_thread

0 commit comments

Comments
 (0)