1 /* 2 Copyright (C) 1997-2014 Sam Lantinga <slouken (at) libsdl.org> 3 4 This software is provided 'as-is', without any express or implied 5 warranty. In no event will the authors be held liable for any damages 6 arising from the use of this software. 7 8 Permission is granted to anyone to use this software for any purpose, 9 including commercial applications, and to alter it and redistribute it 10 freely. 11 */ 12 13 /* Test the thread and mutex locking functions 14 Also exercises the system's signal/thread interaction 15 */ 16 17 #include <signal.h> 18 #include <stdio.h> 19 #include <stdlib.h> /* for atexit() */ 20 21 #include "SDL.h" 22 #include "SDL_mutex.h" 23 #include "SDL_thread.h" 24 25 static SDL_mutex *mutex = NULL; 26 static SDL_threadID mainthread; 27 static SDL_Thread *threads[6]; 28 static volatile int doterminate = 0; 29 30 /* 31 * SDL_Quit() shouldn't be used with atexit() directly because 32 * calling conventions may differ... 33 */ 34 static void 35 SDL_Quit_Wrapper(void) 36 { 37 SDL_Quit(); 38 } 39 40 void 41 printid(void) 42 { 43 SDL_Log("Process %lu: exiting\n", SDL_ThreadID()); 44 } 45 46 void 47 terminate(int sig) 48 { 49 signal(SIGINT, terminate); 50 doterminate = 1; 51 } 52 53 void 54 closemutex(int sig) 55 { 56 SDL_threadID id = SDL_ThreadID(); 57 int i; 58 SDL_Log("Process %lu: Cleaning up...\n", id == mainthread ? 0 : id); 59 doterminate = 1; 60 for (i = 0; i < 6; ++i) 61 SDL_WaitThread(threads[i], NULL); 62 SDL_DestroyMutex(mutex); 63 exit(sig); 64 } 65 66 int SDLCALL 67 Run(void *data) 68 { 69 if (SDL_ThreadID() == mainthread) 70 signal(SIGTERM, closemutex); 71 while (!doterminate) { 72 SDL_Log("Process %lu ready to work\n", SDL_ThreadID()); 73 if (SDL_LockMutex(mutex) < 0) { 74 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't lock mutex: %s", SDL_GetError()); 75 exit(1); 76 } 77 SDL_Log("Process %lu, working!\n", SDL_ThreadID()); 78 SDL_Delay(1 * 1000); 79 SDL_Log("Process %lu, done!\n", SDL_ThreadID()); 80 if (SDL_UnlockMutex(mutex) < 0) { 81 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't unlock mutex: %s", SDL_GetError()); 82 exit(1); 83 } 84 /* If this sleep isn't done, then threads may starve */ 85 SDL_Delay(10); 86 } 87 if (SDL_ThreadID() == mainthread && doterminate) { 88 SDL_Log("Process %lu: raising SIGTERM\n", SDL_ThreadID()); 89 raise(SIGTERM); 90 } 91 return (0); 92 } 93 94 int 95 main(int argc, char *argv[]) 96 { 97 int i; 98 int maxproc = 6; 99 100 /* Enable standard application logging */ 101 SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO); 102 103 /* Load the SDL library */ 104 if (SDL_Init(0) < 0) { 105 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "%s\n", SDL_GetError()); 106 exit(1); 107 } 108 atexit(SDL_Quit_Wrapper); 109 110 if ((mutex = SDL_CreateMutex()) == NULL) { 111 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create mutex: %s\n", SDL_GetError()); 112 exit(1); 113 } 114 115 mainthread = SDL_ThreadID(); 116 SDL_Log("Main thread: %lu\n", mainthread); 117 atexit(printid); 118 for (i = 0; i < maxproc; ++i) { 119 char name[64]; 120 SDL_snprintf(name, sizeof (name), "Worker%d", i); 121 if ((threads[i] = SDL_CreateThread(Run, name, NULL)) == NULL) 122 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create thread!\n"); 123 } 124 signal(SIGINT, terminate); 125 Run(NULL); 126 127 return (0); /* Never reached */ 128 } 129