1 | /* |
2 | Copyright (C) 1997-2021 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 | /* Simple test of the SDL threading code */ |
14 | |
15 | #include <stdio.h> |
16 | #include <stdlib.h> |
17 | #include <signal.h> |
18 | #include <string.h> |
19 | |
20 | #include "SDL.h" |
21 | |
22 | #define NUMTHREADS 10 |
23 | |
24 | static SDL_atomic_t time_for_threads_to_die[NUMTHREADS]; |
25 | |
26 | /* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */ |
27 | static void |
28 | quit(int rc) |
29 | { |
30 | SDL_Quit(); |
31 | exit(rc); |
32 | } |
33 | |
34 | int SDLCALL |
35 | SubThreadFunc(void *data) |
36 | { |
37 | while (!*(int volatile *) data) { |
38 | ; /* SDL_Delay(10); *//* do nothing */ |
39 | } |
40 | return 0; |
41 | } |
42 | |
43 | int SDLCALL |
44 | ThreadFunc(void *data) |
45 | { |
46 | SDL_Thread *sub_threads[NUMTHREADS]; |
47 | int flags[NUMTHREADS]; |
48 | int i; |
49 | int tid = (int) (uintptr_t) data; |
50 | |
51 | SDL_Log("Creating Thread %d\n" , tid); |
52 | |
53 | for (i = 0; i < NUMTHREADS; i++) { |
54 | char name[64]; |
55 | SDL_snprintf(name, sizeof (name), "Child%d_%d" , tid, i); |
56 | flags[i] = 0; |
57 | sub_threads[i] = SDL_CreateThread(SubThreadFunc, name, &flags[i]); |
58 | } |
59 | |
60 | SDL_Log("Thread '%d' waiting for signal\n" , tid); |
61 | while (SDL_AtomicGet(&time_for_threads_to_die[tid]) != 1) { |
62 | ; /* do nothing */ |
63 | } |
64 | |
65 | SDL_Log("Thread '%d' sending signals to subthreads\n" , tid); |
66 | for (i = 0; i < NUMTHREADS; i++) { |
67 | flags[i] = 1; |
68 | SDL_WaitThread(sub_threads[i], NULL); |
69 | } |
70 | |
71 | SDL_Log("Thread '%d' exiting!\n" , tid); |
72 | |
73 | return 0; |
74 | } |
75 | |
76 | int |
77 | main(int argc, char *argv[]) |
78 | { |
79 | SDL_Thread *threads[NUMTHREADS]; |
80 | int i; |
81 | |
82 | /* Enable standard application logging */ |
83 | SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO); |
84 | |
85 | /* Load the SDL library */ |
86 | if (SDL_Init(0) < 0) { |
87 | SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s\n" , SDL_GetError()); |
88 | return (1); |
89 | } |
90 | |
91 | signal(SIGSEGV, SIG_DFL); |
92 | for (i = 0; i < NUMTHREADS; i++) { |
93 | char name[64]; |
94 | SDL_snprintf(name, sizeof (name), "Parent%d" , i); |
95 | SDL_AtomicSet(&time_for_threads_to_die[i], 0); |
96 | threads[i] = SDL_CreateThread(ThreadFunc, name, (void*) (uintptr_t) i); |
97 | |
98 | if (threads[i] == NULL) { |
99 | SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create thread: %s\n" , SDL_GetError()); |
100 | quit(1); |
101 | } |
102 | } |
103 | |
104 | for (i = 0; i < NUMTHREADS; i++) { |
105 | SDL_AtomicSet(&time_for_threads_to_die[i], 1); |
106 | } |
107 | |
108 | for (i = 0; i < NUMTHREADS; i++) { |
109 | SDL_WaitThread(threads[i], NULL); |
110 | } |
111 | SDL_Quit(); |
112 | return (0); |
113 | } |
114 | |