testlock.c (3382B)
1/* 2 Copyright (C) 1997-2014 Sam Lantinga <slouken@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 25static SDL_mutex *mutex = NULL; 26static SDL_threadID mainthread; 27static SDL_Thread *threads[6]; 28static volatile int doterminate = 0; 29 30/* 31 * SDL_Quit() shouldn't be used with atexit() directly because 32 * calling conventions may differ... 33 */ 34static void 35SDL_Quit_Wrapper(void) 36{ 37 SDL_Quit(); 38} 39 40void 41printid(void) 42{ 43 SDL_Log("Process %lu: exiting\n", SDL_ThreadID()); 44} 45 46void 47terminate(int sig) 48{ 49 signal(SIGINT, terminate); 50 doterminate = 1; 51} 52 53void 54closemutex(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 66int SDLCALL 67Run(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 94int 95main(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}