HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
thread_win32_impl.hpp
1// Copyright Take Vos 2021-2022.
2// Distributed under the Boost Software License, Version 1.0.
3// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
4
5#pragma once
6
8
9#include "thread_intf.hpp"
10#include "unfair_mutex.hpp"
11#include "../utility/utility.hpp"
12#include "../char_maps/char_maps.hpp"
13#include "../macros.hpp"
14#include <intrin.h>
15#include <mutex>
16#include <string>
17#include <unordered_map>
18
19hi_export_module(hikogui.concurrency.thread : impl);
20
21hi_export namespace hi::inline v1 {
22
23[[nodiscard]] inline thread_id current_thread_id() noexcept
24{
25 // Thread IDs on Win32 are guaranteed to be not zero.
26 constexpr uint64_t NT_TIB_CurrentThreadID = 0x48;
27 return __readgsdword(NT_TIB_CurrentThreadID);
28}
29
30inline void set_thread_name(std::string_view name) noexcept
31{
32 auto const wname = hi::to_wstring(name);
33 SetThreadDescription(GetCurrentThread(), wname.c_str());
34
35 auto const lock = std::scoped_lock(detail::thread_names_mutex);
36 detail::thread_names.emplace(current_thread_id(), std::string{name});
37}
38
39inline std::vector<bool> mask_int_to_vec(DWORD_PTR rhs) noexcept
40{
41 auto r = std::vector<bool>{};
42
43 r.resize(64);
44 for (std::size_t i = 0; i != r.size(); ++i) {
45 r[i] = to_bool(rhs & (DWORD_PTR{1} << i));
46 }
47
48 return r;
49}
50
51inline DWORD_PTR mask_vec_to_int(std::vector<bool> const &rhs) noexcept
52{
53 DWORD r = 0;
54 for (std::size_t i = 0; i != rhs.size(); ++i) {
55 r |= rhs[i] ? (DWORD{1} << i) : 0;
56 }
57 return r;
58}
59
60[[nodiscard]] inline std::vector<bool> process_affinity_mask()
61{
62 DWORD_PTR process_mask;
63 DWORD_PTR system_mask;
64
65 auto process_handle = GetCurrentProcess();
66
67 if (not GetProcessAffinityMask(process_handle, &process_mask, &system_mask)) {
68 throw os_error(std::format("Could not get process affinity mask.", get_last_error_message()));
69 }
70
71 return mask_int_to_vec(process_mask);
72}
73
75{
76 auto const mask_ = mask_vec_to_int(mask);
77
78 auto const thread_handle = GetCurrentThread();
79
80 auto const old_mask = SetThreadAffinityMask(thread_handle, mask_);
81 if (old_mask == 0) {
82 throw os_error(std::format("Could not set the thread affinity. '{}'", get_last_error_message()));
83 }
84
85 return mask_int_to_vec(old_mask);
86}
87
88[[nodiscard]] inline std::size_t current_cpu_id() noexcept
89{
90 auto const index = GetCurrentProcessorNumber();
91 hi_assert(index < 64);
92 return index;
93}
94
95} // namespace hi::inline v1
Definition of the unfair_mutex.
Rules for working with win32 headers.
constexpr std::wstring to_wstring(std::u32string_view rhs) noexcept
Conversion from UTF-32 to wide-string (UTF-16/32).
Definition to_string.hpp:160
std::vector< bool > process_affinity_mask()
Get the current process CPU affinity mask.
void set_thread_name(std::string_view name) noexcept
Set the name of the current thread.
std::vector< bool > set_thread_affinity_mask(std::vector< bool > const &mask)
Set the current thread CPU affinity mask.
std::size_t current_cpu_id() noexcept
Get the current CPU id.
thread_id current_thread_id() noexcept
Get the current thread id.
hi_export std::string get_last_error_message()
Get the OS error message from the last error received on this thread.
Definition exception_win32_impl.hpp:30
DOXYGEN BUG.
Definition algorithm_misc.hpp:20
T lock(T... args)
T resize(T... args)