/*** Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. File: SpawnThread.NT.cpp Date: Author: Reece ***/ #include #include "Threads.hpp" #include "SpawnThread.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) { // https://github.com/webrtc-uwp/chromium-base/blob/master/threading/platform_thread_win.cc#L129-L136 // Do we care yet? // When targeting older CRTs, _beginthreadex // When targeting at least UWP, CreateThread but _beginthreadex is fine // https://web.archive.org/web/20110928122401/http://www.microsoft.com/msj/1099/win32/win321099.aspx // Even in 1999 it sounded like _tiddata was setup for all modules that may come across our thread // It wasn't until 2005, 6 years later, it became less of a requirement. // Does the modern CRT need it for anything estoeric or evil? // I think so long as we're targeting modern windows its fine to call _beginthreadex for all CRT users // Userland icds, plugins, software not in our build chain, it makes sense for them to have a _fully_ initialized crt // I think I switched it from CreateThread to _beginthreadex at somepoint and i don't remember why 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(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) { SysPushErrorGen("Couldn't initialize thread: {}", debugString); return {false, 0}; } return {true, ok}; } }