testlock: parse arguments using SDLTest_CommonState + extra arguments

main
Anonymous Maarten 2023-03-16 16:56:16 +01:00 committed by Anonymous Maarten
parent 4d86a83fa9
commit 64b739bc1e
1 changed files with 100 additions and 15 deletions

View File

@ -19,11 +19,15 @@
#include <SDL3/SDL.h> #include <SDL3/SDL.h>
#include <SDL3/SDL_main.h> #include <SDL3/SDL_main.h>
#include <SDL3/SDL_test.h>
static SDL_mutex *mutex = NULL; static SDL_mutex *mutex = NULL;
static SDL_threadID mainthread; static SDL_threadID mainthread;
static SDL_Thread *threads[6];
static SDL_AtomicInt doterminate; static SDL_AtomicInt doterminate;
static int nb_threads = 6;
static SDL_Thread **threads;
static int worktime = 1000;
static SDLTest_CommonState *state;
/** /**
* SDL_Quit() shouldn't be used with atexit() directly because * SDL_Quit() shouldn't be used with atexit() directly because
@ -33,11 +37,12 @@ static void
SDL_Quit_Wrapper(void) SDL_Quit_Wrapper(void)
{ {
SDL_Quit(); SDL_Quit();
SDLTest_CommonDestroyState(state);
} }
static void printid(void) static void printid(void)
{ {
SDL_Log("Process %lu: exiting\n", SDL_ThreadID()); SDL_Log("Thread %lu: exiting\n", SDL_ThreadID());
} }
static void terminate(int sig) static void terminate(int sig)
@ -50,30 +55,35 @@ static void closemutex(int sig)
{ {
SDL_threadID id = SDL_ThreadID(); SDL_threadID id = SDL_ThreadID();
int i; int i;
SDL_Log("Process %lu: Cleaning up...\n", id == mainthread ? 0 : id); SDL_Log("Thread %lu: Cleaning up...\n", id == mainthread ? 0 : id);
SDL_AtomicSet(&doterminate, 1); SDL_AtomicSet(&doterminate, 1);
for (i = 0; i < 6; ++i) { if (threads) {
SDL_WaitThread(threads[i], NULL); for (i = 0; i < nb_threads; ++i) {
SDL_WaitThread(threads[i], NULL);
}
SDL_free(threads);
threads = NULL;
} }
SDL_DestroyMutex(mutex); SDL_DestroyMutex(mutex);
exit(sig); exit(sig);
} }
static int SDLCALL static int SDLCALL
Run(void *data) DoWork(void *data)
{ {
if (SDL_ThreadID() == mainthread) { if (SDL_ThreadID() == mainthread) {
(void)signal(SIGTERM, closemutex); (void)signal(SIGTERM, closemutex);
} }
SDL_Log("Thread %lu: starting up", SDL_ThreadID());
while (!SDL_AtomicGet(&doterminate)) { while (!SDL_AtomicGet(&doterminate)) {
SDL_Log("Process %lu ready to work\n", SDL_ThreadID()); SDL_Log("Thread %lu: ready to work\n", SDL_ThreadID());
if (SDL_LockMutex(mutex) < 0) { if (SDL_LockMutex(mutex) < 0) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't lock mutex: %s", SDL_GetError()); SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't lock mutex: %s", SDL_GetError());
exit(1); exit(1);
} }
SDL_Log("Process %lu, working!\n", SDL_ThreadID()); SDL_Log("Thread %lu: start work!\n", SDL_ThreadID());
SDL_Delay(1 * 1000); SDL_Delay(1 * worktime);
SDL_Log("Process %lu, done!\n", SDL_ThreadID()); SDL_Log("Thread %lu: work done!\n", SDL_ThreadID());
if (SDL_UnlockMutex(mutex) < 0) { if (SDL_UnlockMutex(mutex) < 0) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't unlock mutex: %s", SDL_GetError()); SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't unlock mutex: %s", SDL_GetError());
exit(1); exit(1);
@ -82,19 +92,87 @@ Run(void *data)
SDL_Delay(10); SDL_Delay(10);
} }
if (SDL_ThreadID() == mainthread && SDL_AtomicGet(&doterminate)) { if (SDL_ThreadID() == mainthread && SDL_AtomicGet(&doterminate)) {
SDL_Log("Process %lu: raising SIGTERM\n", SDL_ThreadID()); SDL_Log("Thread %lu: raising SIGTERM\n", SDL_ThreadID());
(void)raise(SIGTERM); (void)raise(SIGTERM);
} }
SDL_Log("Thread %lu: exiting!\n", SDL_ThreadID());
return 0; return 0;
} }
#if !defined(_WIN32)
Uint32 hit_timeout(Uint32 interval, void *param) {
SDL_Log("Hit timeout! Sending SIGINT!");
kill(0, SIGINT);
return 0;
}
#endif
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
int i; int i;
int maxproc = 6; #if !defined(_WIN32)
int timeout = 0;
#endif
/* Initialize test framework */
state = SDLTest_CommonCreateState(argv, 0);
if (state == NULL) {
return 1;
}
/* Enable standard application logging */ /* Enable standard application logging */
SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO); SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
/* Parse commandline */
for (i = 1; i < argc;) {
int consumed;
consumed = SDLTest_CommonArg(state, i);
if (!consumed) {
if (SDL_strcmp(argv[i], "--nbthreads") == 0) {
if (argv[i + 1]) {
char *endptr;
nb_threads = SDL_strtol(argv[i + 1], &endptr, 0);
if (endptr != argv[i + 1] && *endptr == '\0' && nb_threads > 0) {
consumed = 2;
}
}
} else if (SDL_strcmp(argv[i], "--worktime") == 0) {
if (argv[i + 1]) {
char *endptr;
nb_threads = SDL_strtol(argv[i + 1], &endptr, 0);
if (endptr != argv[i + 1] && *endptr == '\0' && nb_threads > 0) {
consumed = 2;
}
}
#if !defined(_WIN32)
} else if (SDL_strcmp(argv[i], "--timeout") == 0) {
if (argv[i + 1]) {
char *endptr;
timeout = SDL_strtol(argv[i + 1], &endptr, 0);
if (endptr != argv[i + 1] && *endptr == '\0' && timeout > 0) {
consumed = 2;
}
}
#endif
}
}
if (consumed <= 0) {
static const char *options[] = {
"[--nbthreads NB]",
"[--worktime ms]",
#if !defined(_WIN32)
"[--timeout ms]",
#endif
NULL,
};
SDLTest_CommonLogUsage(state, argv[0], options);
exit(1);
}
i += consumed;
}
threads = SDL_malloc(nb_threads * sizeof(SDL_Thread*));
/* Load the SDL library */ /* Load the SDL library */
if (SDL_Init(0) < 0) { if (SDL_Init(0) < 0) {
@ -114,16 +192,23 @@ int main(int argc, char *argv[])
mainthread = SDL_ThreadID(); mainthread = SDL_ThreadID();
SDL_Log("Main thread: %lu\n", mainthread); SDL_Log("Main thread: %lu\n", mainthread);
(void)atexit(printid); (void)atexit(printid);
for (i = 0; i < maxproc; ++i) { for (i = 0; i < nb_threads; ++i) {
char name[64]; char name[64];
(void)SDL_snprintf(name, sizeof(name), "Worker%d", i); (void)SDL_snprintf(name, sizeof(name), "Worker%d", i);
threads[i] = SDL_CreateThread(Run, name, NULL); threads[i] = SDL_CreateThread(DoWork, name, &threads[i]);
if (threads[i] == NULL) { if (threads[i] == NULL) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create thread!\n"); SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create thread!\n");
} }
} }
#if !defined(_WIN32)
if (timeout) {
SDL_AddTimer(timeout, hit_timeout, NULL);
}
#endif
(void)signal(SIGINT, terminate); (void)signal(SIGINT, terminate);
Run(NULL); DoWork(NULL);
return 0; /* Never reached */ return 0; /* Never reached */
} }