1 /** 2 Native Threading Abstraction 3 4 Copyright: 5 Copyright © 2023-2025, Kitsunebi Games 6 Copyright © 2023-2025, Inochi2D Project 7 8 License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) 9 Authors: Luna Nielsen 10 */ 11 module nulib.threading.internal.thread; 12 import core.attribute : weak; 13 import numem; 14 15 /** 16 Thread ID 17 */ 18 alias ThreadId = size_t; 19 20 /** 21 A thread context. 22 */ 23 struct ThreadContext { 24 void* userData; 25 void function(void* userData) callback; 26 Exception ex; 27 } 28 29 /** 30 Base class of native threading implementations. 31 */ 32 export 33 abstract 34 class NativeThread : NuObject { 35 public: 36 @nogc: 37 38 /** 39 The Thread ID of the calling thread. 40 */ 41 static @property ThreadId selfTid() @safe => _nu_thread_current_tid(); 42 43 /** 44 Creates a new native thread. 45 */ 46 static NativeThread create(ThreadContext ctx) @safe => _nu_thread_new(ctx); 47 48 /** 49 Makes the calling thread sleep for the specified amount 50 of time. 51 52 Params: 53 ms = Miliseconds that the thread should sleep. 54 */ 55 static void sleep(uint ms) @safe { 56 _nu_thread_sleep(ms); 57 } 58 59 /** 60 ID of the thread. 61 */ 62 abstract @property ThreadId tid() @safe; 63 64 /** 65 Whether the thread is currently running. 66 */ 67 abstract @property bool isRunning() @safe; 68 69 /** 70 Starts the given thread. 71 */ 72 abstract void start() @safe; 73 74 /** 75 Forcefully cancels the thread, stopping execution. 76 77 This is not a safe operation, as it may lead to memory 78 leaks and corrupt state. Only use when ABSOLUTELY neccesary. 79 */ 80 abstract void cancel() @system; 81 82 /** 83 Waits for the thread to finish execution. 84 85 Params: 86 timeout = How long to wait for the thread to exit. 87 rethrow = Whether execptions thrown in the thread should be rethrown. 88 */ 89 abstract bool join(uint timeout, bool rethrow) @safe; 90 } 91 92 /** 93 Gets the total number of CPUs in the system. 94 95 Returns: 96 The number of CPUs in the system. 97 */ 98 int totalCPUs() @weak nothrow @nogc { 99 version(Windows) { 100 static struct SYSTEM_INFO { 101 short wProcessorArchitecture; 102 short wReserved; 103 int dwPageSize; 104 void* lpMinimumApplicationAddress; 105 void* lpMaximumApplicationAddress; 106 int* dwActiveProcessorMask; 107 int dwNumberOfProcessors; 108 int dwProcessorType; 109 int dwAllocationGranularity; 110 short wProcessorLevel; 111 short wProcessorRevision; 112 } 113 114 pragma(mangle, "GetSystemInfo") 115 static 116 extern(System) extern void GetSystemInfo(SYSTEM_INFO*) @nogc nothrow; 117 118 SYSTEM_INFO inf; 119 GetSystemInfo(&inf); 120 return inf.dwNumberOfProcessors; 121 } else version(Darwin) { 122 123 pragma(mangle, "sysctlbyname") 124 static 125 extern(C) int sysctlbyname(const(char)*, void*, size_t*, const(void)*, size_t); 126 127 const(char)* nstr = "machdep.cpu.core_count\0"; 128 size_t len = uint.max; 129 uint result; 130 cast(void)sysctlbyname(nstr, &result, &len, null, 0); 131 return cast(int)result; 132 } else version(Posix) { 133 134 import core.sys.posix.unistd : _SC_NPROCESSORS_ONLN, sysconf; 135 return cast(int)sysconf(_SC_NPROCESSORS_ONLN); 136 } else { 137 pragma(msg, "totalCPUs: Platform not supported, will return 1."); 138 139 // Not supported. 140 return 1; 141 } 142 } 143 144 // 145 // FOR IMPLEMENTORS 146 // 147 148 private extern(C): 149 150 version(DigitalMars) version = WeakIsBroken; 151 version(linux) version = WeakIsBroken; 152 version(WeakIsBroken) { 153 154 // Needed on Linux because we can't specify load order. 155 extern(C) extern NativeThread _nu_thread_new(ThreadContext) @trusted @nogc nothrow; 156 extern(C) extern ThreadId _nu_thread_current_tid() @trusted @nogc nothrow; 157 extern(C) extern void _nu_thread_sleep(uint) @trusted @nogc nothrow; 158 } else { 159 160 /* 161 Function which creates a new native thread. 162 */ 163 NativeThread _nu_thread_new(ThreadContext) @trusted @weak @nogc nothrow { return null; } 164 165 /* 166 Function which gets the current Thread ID. 167 */ 168 ThreadId _nu_thread_current_tid() @trusted @weak @nogc nothrow { return 0; } 169 170 /* 171 Function which sleeps the calling thread. 172 */ 173 void _nu_thread_sleep(uint) @trusted @weak @nogc nothrow { } 174 }