Add switch support (BROKEN) and TessesFrameworkFeatures.h and CertificateChain.hpp will be installed properly

This commit is contained in:
2025-04-14 06:30:45 -05:00
parent e8ff8d5bc1
commit 6bc9d0e76c
14 changed files with 385 additions and 44 deletions

View File

@ -52,16 +52,17 @@ option(TESSESFRAMEWORK_ENABLE_APPS "Enable Tesses Framework cli apps" ON)
option(TESSESFRAMEWORK_INSTALL_DEVELOPMENT "Enable Installing Tesses Framework Development Packages" ON)
option(TESSESFRAMEWORK_ENABLE_STATIC "Enable Tesses Framework Static Libraries" ON)
option(TESSESFRAMEWORK_ENABLE_SHARED "Enable Tesses Framework Shared Libraries" ON)
option(TESSESFRAMEWORK_LOGTOFILE "TessesFramework Log to file" ON)
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/include)
if(TESSESFRAMEWORK_ENABLE_MBED)
if(TESSESFRAMEWORK_EMBED_CERT_BUNDLE)
include(cmake/bin2h.cmake)
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/include/CertificateChain.h "#pragma once\n")
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/include/TessesFramework/CertificateChain.h "#pragma once\n")
#target_compile_definitions(TessesFramework PUBLIC TESSESFRAMEWORK_EMBED_CERT_BUNDLE)
bin2h(SOURCE_FILE ${TESSESFRAMEWORK_CERT_BUNDLE_FILE} HEADER_FILE ${CMAKE_CURRENT_BINARY_DIR}/include/CertificateChain.h VARIABLE_NAME CertificateChain APPEND NULL_TERMINATE)
file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/include/CertificateChain.h "\n")
bin2h(SOURCE_FILE ${TESSESFRAMEWORK_CERT_BUNDLE_FILE} HEADER_FILE ${CMAKE_CURRENT_BINARY_DIR}/include/TessesFramework/CertificateChain.h VARIABLE_NAME CertificateChain APPEND NULL_TERMINATE)
file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/include/TessesFramework/CertificateChain.h "\n")
#else()
#target_compile_definitions(TessesFramework PUBLIC TESSESFRAMEWORK_CERT_BUNDLE_FILE=${TESSESFRAMEWORK_CERT_BUNDLE_FILE})
@ -89,13 +90,17 @@ target_include_directories(${TessesFramework_TARGET} PUBLIC ${MBEDTLS_DIR}/inclu
target_link_directories(${TessesFramework_TARGET} PUBLIC ${MBEDTLS_DIR}/lib)
endif()
target_link_libraries(${TessesFramework_TARGET} PUBLIC mbedtls mbedx509 mbedcrypto)
target_include_directories(${TessesFramework_TARGET} PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/include)
endif()
target_include_directories(${TessesFramework_TARGET}
PUBLIC
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>"
)
target_include_directories(${TessesFramework_TARGET}
PUBLIC
"$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/include>"
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>"
)
if("${CMAKE_SYSTEM_NAME}" STREQUAL "NintendoWii" OR "${CMAKE_SYSTEM_NAME}" STREQUAL "NintendoGameCube")
target_link_libraries(${TessesFramework_TARGET} PUBLIC fat)
endif()
@ -145,7 +150,8 @@ install(TARGETS ${TessesFrameworkLibs}
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
)
install(DIRECTORY include/TessesFramework DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/TessesFramework DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/include/TessesFramework DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
install(EXPORT TessesFrameworkTargets
FILE TessesFrameworkTargets.cmake
@ -157,15 +163,13 @@ install(EXPORT TessesFrameworkTargets
include(CMakePackageConfigHelpers)
configure_package_config_file(${CMAKE_CURRENT_SOURCE_DIR}/Config.cmake.in "${CMAKE_CURRENT_BINARY_DIR}/TessesFrameworkConfig.cmake"
INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/TessesFramework)
configure_package_config_file(${CMAKE_CURRENT_SOURCE_DIR}/TessesFrameworkFeatures.h.in "${CMAKE_CURRENT_BINARY_DIR}/TessesFrameworkFeatures.h"
configure_package_config_file(${CMAKE_CURRENT_SOURCE_DIR}/TessesFrameworkFeatures.h.in "${CMAKE_CURRENT_BINARY_DIR}/include/TessesFramework/TessesFrameworkFeatures.h"
INSTALL_DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/TessesFramework/TessesFrameworkFeatures.h)
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/TessesFrameworkConfig.cmake"
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/TessesFramework)
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/TessesFrameworkFeatures.h"
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/TessesFramework)
endif()
if(TESSESFRAMEWORK_ENABLE_EXAMPLES)
add_executable(copyfile examples/copyfile.cpp)
target_link_libraries(copyfile PUBLIC tessesframework)

View File

@ -14,5 +14,9 @@
#if TESSES_FRAMEWORK_FLAG_@TESSESFRAMEWORK_ENABLE_THREADING@
#define TESSESFRAMEWORK_ENABLE_THREADING
#endif
#if TESSES_FRAMEWORK_FLAG_@TESSESFRAMEWORK_LOGTOFILE@
#define TESSESFRAMEWORK_LOGTOFILE
#endif
#undef TESSES_FRAMEWORK_FLAG_OFF
#undef TESSES_FRAMEWORK_FLAG_ON

View File

@ -14,8 +14,10 @@ void print_help(const char* name)
}
int main(int argc, char** argv)
{
TF_Init();
try {
TF_InitWithConsole();
TF_LOG("INIT");
const char* directory = "wwwroot";
bool spa=false;
bool allowListing = false;
@ -54,11 +56,18 @@ int main(int argc, char** argv)
}
}
std::cout << "In folder: " << std::filesystem::absolute(directory).string() << std::endl;
FileServer fs(directory,allowListing, spa);
HttpServer server(port,fs);
server.StartAccepting();
TF_RunEventLoop();
std::cout << "Closing server" << std::endl;
TF_Quit();
}catch(std::exception& ex)
{
TF_LOG(ex.what());
}
return 0;
}

View File

@ -86,12 +86,14 @@ class MyOtherWebServer : public IHttpServer
public:
bool Handle(ServerContext& ctx)
{
TF_LOG("IN HANDLE");
if(ctx.path == "/")
{
std::string name;
if(ctx.queryParams.TryGetFirst("name",name))
{
std::cout << name << std::endl;
TF_LOG(name);
ctx
.WithMimeType("text/plain")
.WithContentDisposition(HttpUtils::Sanitise(name) + ".txt",false)
@ -114,7 +116,7 @@ class MyOtherWebServer : public IHttpServer
int main(int argc, char** argv)
{
TF_Init();
TF_InitWithConsole();
MyOtherWebServer myo;
MyWebServer mws;

View File

@ -30,9 +30,24 @@
namespace Tesses::Framework
{
void TF_Init();
void TF_InitWithConsole();
void TF_ConnectToSelf(uint16_t port);
void TF_RunEventLoop();
void TF_RunEventLoopItteration();
bool TF_IsRunning();
void TF_Quit();
bool TF_GetConsoleEventsEnabled();
void TF_SetConsoleEventsEnabled(bool flag);
void TF_InitConsole();
#define TESSESFRAMEWORK_LOGTOFILE
#if defined(TESSESFRAMEWORK_LOGTOFILE)
void TF_Log(std::string dataToLog);
#endif
#if defined(TESSESFRAMEWORK_LOGTOFILE)
#define TF_LOG(log) Tesses::Framework::TF_Log(log)
#else
#define TF_LOG(log)
#endif
}

View File

@ -15,6 +15,7 @@ namespace Tesses::Framework::Streams
TcpServer(std::string ip, uint16_t port, int32_t backlog);
NetworkStream* GetStream(std::string& ip, uint16_t& port);
~TcpServer();
bool IsValid();
void Close();
};
class NetworkStream : public Stream {

View File

@ -4,6 +4,7 @@
#include <windows.h>
#elif defined(GEKKO)
#include <ogc/lwp.h>
#elif defined(__SWITCH__)
#else
#include <pthread.h>
#endif

View File

@ -2,7 +2,7 @@
#if defined(TESSESFRAMEWORK_ENABLE_MBED)
#if defined(TESSESFRAMEWORK_EMBED_CERT_BUNDLE)
#include "CertificateChain.h"
#include "TessesFramework/CertificateChain.h"
#else
#include "TessesFramework/TextStreams/StreamReader.hpp"
using StreamReader = Tesses::Framework::TextStreams::StreamReader;

View File

@ -3,6 +3,7 @@
#include "TessesFramework/Filesystem/SubdirFilesystem.hpp"
#include <iostream>
#include <unistd.h>
#include "TessesFramework/Common.hpp"
using LocalFilesystem = Tesses::Framework::Filesystem::LocalFilesystem;
using SubdirFilesystem = Tesses::Framework::Filesystem::SubdirFilesystem;
using VFSPath = Tesses::Framework::Filesystem::VFSPath;
@ -38,7 +39,7 @@ namespace Tesses::Framework::Http
}
bool FileServer::SendFile(ServerContext& ctx,VFSPath path)
{
TF_LOG("File: " + path.ToString());
auto strm = this->vfs->OpenFile(path,"rb");
bool retVal = false;
if(strm != nullptr)
@ -58,11 +59,15 @@ namespace Tesses::Framework::Http
if(this->vfs->DirectoryExists(path))
{
TF_LOG("Directory exists");
for(auto f : defaultNames)
{
VFSPath p(path,f);
VFSPath p=path;
p = p / f;
TF_LOG("Trying " + p.ToString());
TF_LOG("Before file exists");
TF_LOG(this->vfs->FileExists(p)?"File Exists" : "File Does Not Exist");
TF_LOG("After file exists");
if(this->vfs->FileExists(p))
return SendFile(ctx,p);
}

View File

@ -8,6 +8,7 @@
#include "TessesFramework/Http/HttpStream.hpp"
#include "TessesFramework/Crypto/MbedHelpers.hpp"
#include "TessesFramework/Threading/Mutex.hpp"
#include "TessesFramework/Common.hpp"
#include <iostream>
using FileStream = Tesses::Framework::Streams::FileStream;
@ -536,20 +537,36 @@ namespace Tesses::Framework::Http
if(http == nullptr) return;
auto svr=this->server;
auto http = this->http;
TF_LOG("Before Creating Thread");
thrd = new Threading::Thread([svr,http]()->void {
while(TF_IsRunning())
{
TF_LOG("after TF_IsRunning");
std::string ip;
uint16_t port;
auto sock =svr->GetStream(ip,port);
if(sock == nullptr) return;
TF_LOG("New Host IP: " + ip + ":" + std::to_string(port));
if(sock == nullptr)
{
std::cout << "STREAM ERROR" << std::endl;
return;
}
TF_LOG("Before entering socket thread");
Threading::Thread thrd2([sock,http,ip,port]()->void {
TF_LOG("In thread to process");
HttpServer::Process(*sock,*http,ip,port,false);
TF_LOG("In thread after process");
delete sock;
});
TF_LOG("Before attach");
thrd2.Detach();
TF_LOG("After attach");
}
});
TF_LOG("Before printing interfaces");
std::cout << "\e[34mInterfaces:\n";
for(auto _ip : NetworkStream::GetIPs())
{
@ -558,7 +575,9 @@ namespace Tesses::Framework::Http
std::cout << "\e[35mhttp://";
std::cout << _ip.second << ":" << std::to_string(this->port) << "/\n";
}
if(!svr->IsValid()) std::cout << "\e[31mError, we failed to bind or something\e[39m\n" << std::endl;
std::cout << "\e[31mAlmost Ready to Listen\e[39m\n";
TF_LOG("After printing interfaces");
}
HttpServer::~HttpServer()
{
@ -834,7 +853,7 @@ namespace Tesses::Framework::Http
}
void HttpServer::Process(Stream& strm, IHttpServer& server, std::string ip, uint16_t port, bool encrypted)
{
TF_LOG("In process");
while(true)
{
BufferedStream bStrm(strm);
@ -863,6 +882,8 @@ namespace Tesses::Framework::Http
ctx.originalPath = pp[0];
ctx.path = ctx.originalPath;
TF_LOG(ctx.method + " with path " + ctx.path);
auto queryPart = pp[1];
if(!queryPart.empty())
{

View File

@ -1,6 +1,6 @@
#include "TessesFramework/Streams/NetworkStream.hpp"
#include "TessesFramework/Http/HttpUtils.hpp"
#include <iostream>
using HttpUtils = Tesses::Framework::Http::HttpUtils;
#if defined(TESSESFRAMEWORK_ENABLE_NETWORKING)
@ -36,7 +36,7 @@ extern "C" {
#if defined(GEKKO)
extern "C" uint32_t if_config( char *local_ip, char *netmask, char *gateway,bool use_dhcp, int max_retries);
#elif !defined(_WIN32) && !defined(__ANDROID__)
#elif !defined(_WIN32) && !defined(__ANDROID__) && !defined(__SWITCH__)
#include <ifaddrs.h>
#endif
@ -75,7 +75,7 @@ namespace Tesses::Framework::Streams {
char gateway[16];
if_config(localIp,netmask, gateway, true, 1);
ipConfig.push_back(std::pair<std::string,std::string>("net",localIp));
#elif defined(_WIN32) || defined(__ANDROID__)
#elif defined(_WIN32) || defined(__ANDROID__) || defined(__SWITCH__)
#else
struct ifaddrs *ifAddrStruct = NULL;
@ -228,6 +228,7 @@ namespace Tesses::Framework::Streams {
this->sock = NETWORK_SOCKET(AF_INET, SOCK_STREAM, 0);
if(this->sock < 0)
{
std::cout << "FAILED TO CREATE SOCKET FOR SOME REASON" << std::endl;
this->valid=false;
return;
}
@ -245,17 +246,23 @@ namespace Tesses::Framework::Streams {
#endif
if(NETWORK_BIND(this->sock, (const sockaddr*)&addr, (socklen_t)sizeof(addr)) != 0)
{
std::cout << "FAILED TO BIND FOR SOME REASON" << std::endl;
this->valid = false;
return;
}
if(NETWORK_LISTEN(this->sock, backlog) != 0)
{
std::cout << "FAILED TO LISTEN FOR SOME REASON" << std::endl;
this->valid = false;
return;
}
this->valid = true;
}
bool TcpServer::IsValid()
{
return this->valid;
}
TcpServer::TcpServer(std::string ip, uint16_t port, int32_t backlog)
{
this->owns=true;
@ -345,14 +352,14 @@ namespace Tesses::Framework::Streams {
if(ipV6)
{
#if defined(AF_INET6)
this->sock = socket(AF_INET6, datagram ? SOCK_DGRAM : SOCK_STREAM, 0);
this->sock = NETWORK_SOCKET(AF_INET6, datagram ? SOCK_DGRAM : SOCK_STREAM, 0);
if(this->sock >= 0) this->success=true;
#endif
}
else
{
#if defined(AF_INET)
this->sock = socket(AF_INET, datagram ? SOCK_DGRAM : SOCK_STREAM, 0);
this->sock = NETWORK_SOCKET(AF_INET, datagram ? SOCK_DGRAM : SOCK_STREAM, 0);
if(this->sock >= 0) this->success=true;
#endif
}
@ -563,6 +570,7 @@ namespace Tesses::Framework::Streams {
int noDelay2 = noDelay;
NETWORK_SETSOCKOPT(this->sock, SOL_SOCKET, TCP_NODELAY, (const char*)&noDelay2,(socklen_t)sizeof(noDelay2));
}
}
#else
namespace Tesses::Framework::Streams {
@ -587,6 +595,10 @@ TcpServer::~TcpServer()
{
}
bool TcpServer::IsValid()
{
return this->valid;
}
void TcpServer::Close()
{

View File

@ -5,6 +5,10 @@
#if defined(_WIN32)
#include <windows.h>
#include <cstdio>
#elif defined(__SWITCH__)
extern "C" {
#include <switch.h>
}
#elif defined(GEKKO)
#include <stdio.h>
#include <stdlib.h>
@ -25,10 +29,23 @@ static GXRModeObj *rmode = NULL;
#endif
#if defined(TESSESFRAMEWORK_ENABLE_THREADING)
#include "TessesFramework/Threading/Mutex.hpp"
#endif
namespace Tesses::Framework
{
#if defined(TESSESFRAMEWORK_ENABLE_THREADING) && (defined(GEKKO) || defined(__SWITCH__))
namespace Threading
{
extern void JoinAllThreads();
extern void LookForFinishedThreads();
}
#endif
volatile static bool isRunningSig=true;
volatile static std::atomic<bool> isRunning;
volatile static std::atomic<bool> gaming_console_events=true;
void TF_ConnectToSelf(uint16_t port)
{
Tesses::Framework::Streams::NetworkStream ns("127.0.0.1",port,false,false,false);
@ -49,21 +66,52 @@ namespace Tesses::Framework
TF_RunEventLoopItteration();
}
}
#if defined(__SWITCH__)
bool initedConsole=false;
PadState default_pad;
#endif
void TF_RunEventLoopItteration()
{
#if defined(TESSESFRAMEWORK_ENABLE_THREADING) && (defined(GEKKO) || defined(__SWITCH__))
Tesses::Framework::Threading::LookForFinishedThreads();
#endif
if(!isRunningSig) isRunning=false;
#if defined(GEKKO)
if(gaming_console_events)
{
PAD_ScanPads();
if(PAD_ButtonsDown(0) & PAD_BUTTON_START) isRunning=false;
}
#elif defined(__SWITCH__)
if(gaming_console_events)
{
if(!appletMainLoop()) isRunning=false;
padUpdate(&default_pad);
u64 kDown = padGetButtonsDown(&default_pad);
if (kDown & HidNpadButton_Plus)
isRunning=false;
if(initedConsole)
consoleUpdate(NULL);
}
#endif
}
void TF_Quit()
{
isRunning=false;
#if defined(TESSESFRAMEWORK_ENABLE_THREADING) && (defined(GEKKO) || defined(__SWITCH__))
Tesses::Framework::Threading::JoinAllThreads();
#endif
}
void TF_Init()
{
#if defined(_WIN32)
@ -91,6 +139,29 @@ if (iResult != 0) {
#endif
WPAD_Init();
#endif
#elif defined(__SWITCH__)
padConfigureInput(1, HidNpadStyleSet_NpadStandard);
padInitializeDefault(&default_pad);
socketInitializeDefault();
// Initialize the default gamepad (which reads handheld mode inputs as well as the first connected controller)
#else
signal(SIGPIPE,SIG_IGN);
signal(SIGINT,_sigInt);
#endif
}
bool TF_GetConsoleEventsEnabled()
{
return gaming_console_events;
}
void TF_SetConsoleEventsEnabled(bool flag)
{
gaming_console_events=flag;
}
void TF_InitConsole()
{
#if defined(GEKKO)
rmode = VIDEO_GetPreferredMode(NULL);
// Allocate memory for the display in the uncached region
@ -121,9 +192,34 @@ if (iResult != 0) {
// we can use variables for this with format codes too
// e.g. printf ("\x1b[%d;%dH", row, column );
printf("\x1b[2;0H");
#else
signal(SIGPIPE,SIG_IGN);
signal(SIGINT,_sigInt);
#elif defined(__SWITCH__)
consoleInit(NULL);
initedConsole=true;
#endif
}
void TF_InitWithConsole()
{
TF_Init();
TF_InitConsole();
#if defined(TESSESFRAMEWORK_LOGTOFILE)
printf("Enabled Logging\n");
#endif
}
#if defined(TESSESFRAMEWORK_LOGTOFILE)
#if defined(TESSESFRAMEWORK_ENABLE_THREADING)
Tesses::Framework::Threading::Mutex log_mtx;
#endif
void TF_Log(std::string txtToLog)
{
#if defined(TESSESFRAMEWORK_ENABLE_THREADING)
log_mtx.Lock();
#endif
FILE* f = fopen("TF_Log.log","a");
fprintf(f,"%s\n",txtToLog.c_str());
fclose(f);
#if defined(TESSESFRAMEWORK_ENABLE_THREADING)
log_mtx.Unlock();
#endif
}
#endif
}

View File

@ -5,6 +5,10 @@
#include <windows.h>
#elif defined(GEKKO)
#include <ogc/mutex.h>
#elif defined(__SWITCH__)
extern "C" {
#include <switch/kernel/mutex.h>
}
#else
#include <pthread.h>
#endif
@ -19,6 +23,8 @@ namespace Tesses::Framework::Threading
HANDLE mtx;
#elif defined(GEKKO)
mutex_t mtx;
#elif defined(__SWITCH__)
RMutex mtx;
#else
pthread_mutex_t mtx;
pthread_mutexattr_t attr;
@ -29,6 +35,8 @@ namespace Tesses::Framework::Threading
CloseHandle(mtx);
#elif defined(GEKKO)
LWP_MutexDestroy(mtx);
#elif defined(__SWITCH__)
#else
pthread_mutex_destroy(&mtx);
pthread_mutexattr_destroy(&attr);
@ -45,6 +53,8 @@ namespace Tesses::Framework::Threading
#elif defined(GEKKO)
md->mtx = LWP_MUTEX_NULL;
LWP_MutexInit(&md->mtx, true);
#elif defined(__SWITCH__)
rmutexInit(&md->mtx);
#else
pthread_mutexattr_init(&md->attr);
pthread_mutexattr_settype(&md->attr,PTHREAD_MUTEX_RECURSIVE);
@ -61,6 +71,8 @@ namespace Tesses::Framework::Threading
WaitForSingleObject(md->mtx, INFINITE);
#elif defined(GEKKO)
LWP_MutexLock(md->mtx);
#elif defined(__SWITCH__)
rmutexLock(&md->mtx);
#else
pthread_mutex_lock(&md->mtx);
#endif
@ -74,6 +86,8 @@ namespace Tesses::Framework::Threading
ReleaseMutex(md->mtx);
#elif defined(GEKKO)
LWP_MutexUnlock(md->mtx);
#elif defined(__SWITCH__)
rmutexUnlock(&md->mtx);
#else
pthread_mutex_unlock(&md->mtx);
#endif
@ -87,6 +101,8 @@ namespace Tesses::Framework::Threading
return WaitForSingleObject(md->mtx, 100) == WAIT_OBJECT_0;
#elif defined(GEKKO)
return LWP_MutexTryLock(md->mtx) == 0;
#elif defined(__SWITCH__)
return rmutexTryLock(&md->mtx);
#else
return pthread_mutex_trylock(&md->mtx) == 0;
#endif

View File

@ -1,10 +1,150 @@
#include "TessesFramework/Threading/Thread.hpp"
#include <iostream>
#include <memory>
#include "TessesFramework/Threading/Mutex.hpp"
#include "TessesFramework/Common.hpp"
#if defined(__SWITCH__)
extern "C" {
#include <switch.h>
#include <switch/kernel/thread.h>
}
using NxThread = Thread;
#endif
namespace Tesses::Framework::Threading
{
#if defined(TESSESFRAMEWORK_ENABLE_THREADING)
#if defined(__SWITCH__) || defined(GEKKO)
Mutex needed_to_be_joined_mtx;
class NeedToBeJoinnedThread {
#if defined(GEKKO)
static void* cb(void* data)
#elif defined(__SWITCH__)
static void cb(void* data)
#endif
{
auto ntbjt = static_cast<NeedToBeJoinnedThread*>(data);
ntbjt->hasInvoked=true;
TF_LOG("About to call thread func");
if(ntbjt->_cb)
ntbjt->_cb();
TF_LOG("Finished calling thread func");
ntbjt->hasExited=true;
#if defined(GEKKO)
return NULL;
#endif
}
std::function<void()> _cb;
std::atomic<bool> hasInvoked=false;
#if defined(__SWITCH__)
NxThread thrd;
#elif defined(GEKKO)
lwp_t thrd;
#endif
public:
NeedToBeJoinnedThread(std::function<void()> cb)
{
this->_cb = cb;
joinned=false;
joinning=false;
hasExited=false;
#if defined(GEKKO)
LWP_CreateThread(&thrd, cb, static_cast<void*>(this), nullptr,12000, 98);
#elif defined(__SWITCH__)
TF_LOG("Before Thread create");
Result rc = threadCreate(&thrd,this->cb,
static_cast<void*>(this), NULL, 0x100000,
0x20 , 2);
if (R_FAILED(rc))
{
this->hasExited=true;
this->joinned=true;
TF_LOG("Failed to create Thread");
return;
}
TF_LOG("After Thread create, before starting");
rc = threadStart(&thrd);
if (R_FAILED(rc))
{
TF_LOG("Failed to start thread");
threadClose(&thrd);
this->hasExited=true;
this->joinned=true;
return;
}
TF_LOG("Starting");
#endif
}
std::atomic<bool> joinned;
std::atomic<bool> joinning;
std::atomic<bool> hasExited;
void Join();
void WaitTillInvoked()
{
while(!hasInvoked);
TF_LOG("Invoked!");
}
};
void NeedToBeJoinnedThread::Join()
{
if(joinning)
{
return;
}
joinning=true;
#if defined(__SWITCH__)
threadWaitForExit(&this->thrd);
threadClose(&this->thrd);
#elif defined(GEKKO)
void* res;
LWP_JoinThread(this->thrd,&res);
#endif
joinned=true;
//start the joinning process
}
std::vector<std::shared_ptr<NeedToBeJoinnedThread>> needToBeJoinnedThread;
void JoinAllThreads()
{
needed_to_be_joined_mtx.Lock();
for(auto item : needToBeJoinnedThread)
{
item->Join();
}
needToBeJoinnedThread.clear();
needed_to_be_joined_mtx.Unlock();
}
void LookForFinishedThreads()
{
needed_to_be_joined_mtx.Lock();
for(auto index = needToBeJoinnedThread.begin(); index < needToBeJoinnedThread.end(); index++)
{
auto& idx = *index;
if(idx->hasExited)
{
if(idx->joinning) while(!idx->joinned);
TF_LOG("ABOUT TO JOIN");
idx->Join();
TF_LOG("JOINNED");
needToBeJoinnedThread.erase(index);
index--;
}
}
needed_to_be_joined_mtx.Unlock();
}
#endif
class ThreadHiddenFieldData : public HiddenFieldData {
public:
#if defined(_WIN32)
@ -16,7 +156,8 @@ namespace Tesses::Framework::Threading
#elif defined(GEKKO)
lwp_t thrd;
#elif defined(__SWITCH__) || defined(GEKKO)
std::shared_ptr<NeedToBeJoinnedThread> thread;
#else
pthread_t thrd;
#endif
@ -30,6 +171,8 @@ namespace Tesses::Framework::Threading
#if defined(_WIN32)
static DWORD __stdcall cb(LPVOID data)
#elif defined(__SWITCH__)
static void cb(void* data)
#else
static void* cb(void* data)
#endif
@ -39,8 +182,10 @@ namespace Tesses::Framework::Threading
auto fn = thrd->fn;
thrd->hasInvoked=true;
fn();
#if !defined(_WIN32)
#if !defined(_WIN32) && !defined(__SWITCH__)
return NULL;
#elif(__SWITCH__)
#else
return 0;
#endif
@ -55,26 +200,37 @@ namespace Tesses::Framework::Threading
data->fn = fn;
#if defined(_WIN32)
data->thrd = CreateThread(NULL,0,cb,static_cast<LPVOID>(data), 0, &data->thrdId);
#elif defined(GEKKO)
auto res = LWP_CreateThread(&data->thrd, cb, static_cast<void*>(data), nullptr,12000, 98);
while(!data->hasInvoked);
#elif defined(__SWITCH__) || defined(GEKKO)
data->thread = std::make_shared<NeedToBeJoinnedThread>(fn);
data->thread->WaitTillInvoked();
//threadCreate(,cb,static_cast<void*>(data),NULL,8000000,0x00,-2);
#else
pthread_create(&data->thrd,NULL,cb,static_cast<void*>(data));
while(!data->hasInvoked);
//thrd_create(&thrd, cb, static_cast<void*>(this));
#endif
while(!data->hasInvoked);
#endif
}
void Thread::Detach()
{
#if defined(TESSESFRAMEWORK_ENABLE_THREADING)
auto data = this->data.GetField<ThreadHiddenFieldData*>();
#if !defined(GEKKO)
#if defined(_WIN32)
CloseHandle(data->thrd);
#elif defined(__SWITCH__) || defined(GEKKO)
TF_LOG("Detaching");
needed_to_be_joined_mtx.Lock();
needToBeJoinnedThread.push_back(data->thread);
needed_to_be_joined_mtx.Unlock();
TF_LOG("Detached!");
#else
pthread_detach(data->thrd);
#endif
#endif
#endif
}
@ -84,9 +240,8 @@ namespace Tesses::Framework::Threading
auto data = this->data.GetField<ThreadHiddenFieldData*>();
#if defined(_WIN32)
WaitForSingleObject(data->thrd, INFINITE);
#elif defined(GEKKO)
void* res;
LWP_JoinThread(data->thrd,&res);
#elif defined(__SWITCH__) || defined(GEKKO)
data->thread->Join();
#else
pthread_join(data->thrd,NULL);
#endif