Skip to content
Closed
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
3 changes: 1 addition & 2 deletions examples/0040.thread/thread.cc
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
#include <chrono>
#include <fast_io.h>

int main()
Expand All @@ -19,7 +18,7 @@ int main()
::fast_io::println("the child thread id is: ", ::fast_io::this_thread::get_id());
#endif
// ::fflush(stdout);
::fast_io::this_thread::sleep_for(::std::chrono::seconds{1});
::fast_io::this_thread::sleep_for(::fast_io::unix_timestamp{.seconds = 1});
},
5};

Expand Down
3 changes: 2 additions & 1 deletion include/fast_io_hosted/platforms/systemcall_details.h
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,8 @@ inline void sys_close_throw_error(int &fd)
}
#endif
}
#if (!defined(__NEWLIB__) || defined(__CYGWIN__)) && !defined(_WIN32) && __has_include(<dirent.h>) && !defined(_PICOLIBC__)

#if !defined(_WIN32) && __has_include(<dirent.h>) && !defined(_PICOLIBC__)

namespace posix
{
Expand Down
50 changes: 1 addition & 49 deletions include/fast_io_hosted/threads/thread/dos.h
Original file line number Diff line number Diff line change
@@ -1,14 +1,6 @@
#pragma once

// std
#include <chrono>
#include <ranges>
#include <cstdint>
#include <utility>
#include <functional>
#include <type_traits>
// system
#include <dpmi.h>


namespace fast_io
{
Expand All @@ -27,46 +19,6 @@ inline constexpr dos_thread_id get_id() noexcept
return 0u;
}

template <typename Rep, typename Period>
inline
#if __cpp_constexpr >= 202207L
// https://en.cppreference.com/w/cpp/compiler_support/23.html#cpp_constexpr_202207L
// for reduce some warning purpose
constexpr
#endif
void sleep_for(::std::chrono::duration<Rep, Period> const &sleep_duration) noexcept
{
auto const us64{::std::chrono::duration_cast<::std::chrono::microseconds>(sleep_duration).count()};
if (us64 <= 0)
{
return;
}
auto remaining{static_cast<::std::uint_least64_t>(us64)};
constexpr ::std::uint_least64_t max_chunk{static_cast<::std::uint_least64_t>(static_cast<unsigned>(-1))};
while (remaining != 0)
{
auto const chunk{remaining > max_chunk ? max_chunk : remaining};
::fast_io::details::posix::my_usleep(static_cast<unsigned>(chunk));
remaining -= chunk;
}
}

template <typename Clock, typename Duration>
inline
#if __cpp_constexpr >= 202207L
// https://en.cppreference.com/w/cpp/compiler_support/23.html#cpp_constexpr_202207L
// for reduce some warning purpose
constexpr
#endif
void sleep_until(::std::chrono::time_point<Clock, Duration> const &expect_time) noexcept
{
auto const now{Clock::now()};
if (now < expect_time)
{
::fast_io::dos::this_thread::sleep_for(expect_time - now);
}
}

template <::std::int_least64_t off_to_epoch>
inline
#if __cpp_constexpr >= 202207L
Expand Down
15 changes: 15 additions & 0 deletions include/fast_io_hosted/threads/thread/impl.h
Original file line number Diff line number Diff line change
@@ -1,14 +1,29 @@
#pragma once

// std
#include <ranges>
#include <cstdint>
#include <utility>
#include <functional>
#include <type_traits>

#if (defined(_WIN32) && !defined(__WINE__)) && !defined(__CYGWIN__)
#include "win32.h"
#ifndef _WIN32_WINDOWS
#include "nt.h"
#endif
#elif defined(__MSDOS__) || defined(__DJGPP__)
#include <dpmi.h>
#include "dos.h"
#elif defined(__wasi__)
#include <wasi/api.h>
#include "wasi.h"
#elif !defined(__SINGLE_THREAD__) && !defined(__NEWLIB__) && !defined(__MSDOS__) && __has_include(<pthread.h>)
#include <pthread.h>
#include <sched.h>
#include <time.h>
#include <unistd.h>
#include "pthread.h"
#elif defined(__NEWLIB__)
#include "newlib.h"
#endif
105 changes: 105 additions & 0 deletions include/fast_io_hosted/threads/thread/newlib.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
#pragma once

namespace fast_io
{
namespace details::posix
{
extern unsigned my_usleep(unsigned usec) noexcept __asm__("_usleep");
extern int sched_yield() noexcept __asm__("_sched_yield");
} // namespace details::posix

namespace newlib::this_thread
{

using dos_thread_id = unsigned;

inline constexpr dos_thread_id get_id() noexcept
{
return 0u;
}


template <::std::int_least64_t off_to_epoch>
inline
#if __cpp_constexpr >= 202207L
// https://en.cppreference.com/w/cpp/compiler_support/23.html#cpp_constexpr_202207L
// for reduce some warning purpose
constexpr
#endif
void sleep_for(::fast_io::basic_timestamp<off_to_epoch> const &sleep_duration) noexcept
{
if (sleep_duration.seconds < 0)
{
return;
}

constexpr ::std::uint_least64_t mul_factor{::fast_io::uint_least64_subseconds_per_second / 1000000u};

auto const us64{
static_cast<::std::uint_least64_t>(static_cast<::std::uint_least64_t>(sleep_duration.seconds) * 1000000u +
sleep_duration.subseconds / mul_factor)};
if (us64 == 0)
{
return;
}

auto remaining{us64};
constexpr ::std::uint_least64_t max_chunk{static_cast<::std::uint_least64_t>(static_cast<unsigned>(-1))};
while (remaining != 0)
{
auto const chunk{remaining > max_chunk ? max_chunk : remaining};
::fast_io::details::posix::my_usleep(static_cast<unsigned>(chunk));
remaining -= chunk;
}
}

template <::std::int_least64_t off_to_epoch>
inline
#if __cpp_constexpr >= 202207L
// https://en.cppreference.com/w/cpp/compiler_support/23.html#cpp_constexpr_202207L
// for reduce some warning purpose
constexpr
#endif
void sleep_until(::fast_io::basic_timestamp<off_to_epoch> const &expect_time) noexcept
{
if (expect_time.seconds < 0)
{
return;
}

auto const unix_expect{static_cast<::fast_io::unix_timestamp>(expect_time)};
auto const now{::fast_io::posix_clock_gettime(::fast_io::posix_clock_id::realtime)};
if (!(now < unix_expect))
{
return;
}

auto const delta{unix_expect - now};
::fast_io::newlib::this_thread::sleep_for(delta);
}

inline
#if __cpp_constexpr >= 202207L
// https://en.cppreference.com/w/cpp/compiler_support/23.html#cpp_constexpr_202207L
// for reduce some warning purpose
constexpr
#endif
void yield() noexcept
{
::fast_io::details::posix::sched_yield();
}

} // namespace newlib::this_thread

#if defined(__NEWLIB__)

namespace this_thread
{
using ::fast_io::newlib::this_thread::get_id;
using ::fast_io::newlib::this_thread::sleep_for;
using ::fast_io::newlib::this_thread::sleep_until;
using ::fast_io::newlib::this_thread::yield;
} // namespace this_thread
#endif

} // namespace fast_io
70 changes: 0 additions & 70 deletions include/fast_io_hosted/threads/thread/nt.h
Original file line number Diff line number Diff line change
@@ -1,12 +1,5 @@
#pragma once

#include <chrono>
#include <ranges>
#include <cstdint>
#include <utility>
#include <functional>
#include <type_traits>

namespace fast_io
{
namespace win32::nt
Expand Down Expand Up @@ -300,31 +293,6 @@ inline
return static_cast<::std::uint_least32_t>(reinterpret_cast<::std::size_t>(teb->ClientId.UniqueThread));
}

template <bool zw = false, typename Rep, typename Period>
inline
#if __cpp_constexpr >= 202207L
// https://en.cppreference.com/w/cpp/compiler_support/23.html#cpp_constexpr_202207L
// for reduce some warning purpose
constexpr
#endif
void sleep_for(::std::chrono::duration<Rep, Period> const &sleep_duration)
{
auto const count{static_cast<::std::uint_least64_t>(
::std::chrono::duration_cast<::std::chrono::microseconds>(sleep_duration).count() * 10u +
::std::chrono::duration_cast<::std::chrono::nanoseconds>(sleep_duration).count() / 100u % 10u)};

if (count > static_cast<::std::uint_least64_t>(::std::numeric_limits<::std::int_least64_t>::max()))
{
::fast_io::throw_nt_error(0xC000000D);
}

auto val{-static_cast<::std::int_least64_t>(count)};
::std::uint_least32_t status{::fast_io::win32::nt::nt_delay_execution<zw>(false, __builtin_addressof(val))};
if (status) [[unlikely]]
{
::fast_io::throw_nt_error(status);
}
}

template <bool zw = false, ::std::int_least64_t off_to_epoch>
inline
Expand Down Expand Up @@ -357,44 +325,6 @@ inline
}
}

template <bool zw = false, typename Clock, typename Duration>
inline
#if __cpp_constexpr >= 202207L
// https://en.cppreference.com/w/cpp/compiler_support/23.html#cpp_constexpr_202207L
// for reduce some warning purpose
constexpr
#endif
void sleep_until(::std::chrono::time_point<Clock, Duration> const &expect_time)
{
auto const unix_ts = ::std::chrono::duration_cast<std::chrono::seconds>(
expect_time.time_since_epoch())
.count();
auto const unix_subsec_ts = ::std::chrono::duration_cast<std::chrono::nanoseconds>(
expect_time.time_since_epoch())
.count() /
100u % 10000000u;

auto const unix_to_nt_secs{static_cast<::std::int_least64_t>(unix_ts) + 11644473600};
if (unix_to_nt_secs < 0) [[unlikely]]
{
::fast_io::throw_nt_error(0xC000000D);
}

auto const count{static_cast<::std::uint_least64_t>(unix_to_nt_secs) * 10000000u + static_cast<::std::uint_least64_t>(unix_subsec_ts)};

if (count > static_cast<::std::uint_least64_t>(::std::numeric_limits<::std::int_least64_t>::max()))
{
::fast_io::throw_nt_error(0xC000000D);
}

auto nt_ts{static_cast<::std::int_least64_t>(count)};
::std::uint_least32_t status{::fast_io::win32::nt::nt_delay_execution<zw>(false, __builtin_addressof(nt_ts))};
if (status) [[unlikely]]
{
::fast_io::throw_nt_error(status);
}
}

template <bool zw = false, ::std::int_least64_t off_to_epoch>
inline
#if __cpp_constexpr >= 202207L
Expand Down
70 changes: 1 addition & 69 deletions include/fast_io_hosted/threads/thread/pthread.h
Original file line number Diff line number Diff line change
@@ -1,17 +1,6 @@
#pragma once

// std
#include <chrono>
#include <ranges>
#include <cstdint>
#include <utility>
#include <functional>
#include <type_traits>
// system
#include <pthread.h>
#include <sched.h>
#include <time.h>
#include <unistd.h>


namespace fast_io
{
Expand Down Expand Up @@ -237,63 +226,6 @@ inline
return ::fast_io::noexcept_call(::pthread_self);
}

template <typename Rep, typename Period>
inline
#if __cpp_constexpr >= 202207L
// https://en.cppreference.com/w/cpp/compiler_support/23.html#cpp_constexpr_202207L
// for reduce some warning purpose
constexpr
#endif
void sleep_for(::std::chrono::duration<Rep, Period> const &sleep_duration) noexcept
{
auto const ns64{::std::chrono::duration_cast<::std::chrono::nanoseconds>(sleep_duration).count()};
if (ns64 <= 0)
{
return;
}
::timespec req{};
req.tv_sec = static_cast<::time_t>(ns64 / 1'000'000'000LL);
req.tv_nsec = static_cast<long>(ns64 % 1'000'000'000LL);
(void)::fast_io::noexcept_call(::nanosleep, __builtin_addressof(req), nullptr);
}

template <typename Clock, typename Duration>
inline
#if __cpp_constexpr >= 202207L
// https://en.cppreference.com/w/cpp/compiler_support/23.html#cpp_constexpr_202207L
// for reduce some warning purpose
constexpr
#endif
void sleep_until(::std::chrono::time_point<Clock, Duration> const &expect_time) noexcept
{
auto const now{Clock::now()};
if (now < expect_time)
{
auto const ns64{::std::chrono::duration_cast<::std::chrono::nanoseconds>(expect_time - now).count()};
if (ns64 <= 0)
{
return;
}
::timespec delta{};
delta.tv_sec = static_cast<::time_t>(ns64 / 1'000'000'000LL);
delta.tv_nsec = static_cast<long>(ns64 % 1'000'000'000LL);
#if defined(CLOCK_REALTIME) && defined(TIMER_ABSTIME)
::timespec abs_ts{};
(void)::fast_io::noexcept_call(::clock_gettime, CLOCK_REALTIME, __builtin_addressof(abs_ts));
abs_ts.tv_sec += delta.tv_sec;
abs_ts.tv_nsec += delta.tv_nsec;
if (abs_ts.tv_nsec >= 1'000'000'000L)
{
abs_ts.tv_nsec -= 1'000'000'000L;
++abs_ts.tv_sec;
}
::fast_io::noexcept_call(::clock_nanosleep, CLOCK_REALTIME, TIMER_ABSTIME, __builtin_addressof(abs_ts), nullptr);
#else
::fast_io::noexcept_call(::nanosleep, __builtin_addressof(delta), nullptr);
#endif
}
}

template <::std::int_least64_t off_to_epoch>
inline
#if __cpp_constexpr >= 202207L
Expand Down
Loading