/*** Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. File: AuSpawnThread.NT.cpp Date: Author: Reece ***/ #include #include "AuThreads.hpp" #include "AuSpawnThread.hpp" #if defined(AURORA_PLATFORM_WIN32) #include #include #endif namespace Aurora::Threading::Threads { AuPair /*success, oshandle*/ SpawnThread(const AuFunction &entrypoint, const AuString &debugString, AuUInt32 staskSize) { if (!entrypoint) { return {false, 0}; } // i dont like this allocate auto callbackClone = _new AuFunction(entrypoint); if (!callbackClone) { return {false, 0}; } static auto callVoidPtr_f = [](void *that) -> void { auto handle = reinterpret_cast *>(that); auto callMe = *handle; delete handle; callMe(); }; unsigned(WINAPI * OSEP_f)(void *) = [](void *that) -> unsigned { callVoidPtr_f(that); return 0; }; DWORD(WINAPI * OSCreateThreadEP_f)(void *) = [](void *that) -> DWORD { callVoidPtr_f(that); return 0; }; #if defined(_DLL) /* dynamic system vcruntime of the 2016+ crt */ || \ !defined(AURORA_PLATFORM_WIN32) // msvcrt.dll era code should also prefer _beginthreadex auto handle = CreateThread(NULL, staskSize, OSCreateThreadEP_f, reinterpret_cast(callbackClone), NULL, NULL); if (!handle) { handle = INVALID_HANDLE_VALUE; SysPushErrorGen("Couldn't create locked thread: {}", debugString); return { false, 0 }; } return { true, reinterpret_cast(handle) }; #else #if defined(AURORA_PLATFORM_WIN32) BOOL a {}; if (AuxUlibIsDLLSynchronizationHeld(&a)) { if (a) { auto handle = CreateThread(NULL, staskSize, OSCreateThreadEP_f, reinterpret_cast(callbackClone), NULL, NULL); if (!handle) { handle = INVALID_HANDLE_VALUE; SysPushErrorGen("Couldn't create locked thread: {}", debugString); return {false, 0}; } return {true, reinterpret_cast(handle)}; } } #endif auto ok = _beginthreadex(nullptr, staskSize, OSEP_f, callbackClone, 0, 0); if ((ok == -1L) || (ok == 0)) { SysPushErrorGen("Couldn't initialize thread: {}", debugString); return {false, 0}; } return {true, ok}; #endif } }