diff options
author | 3gg <3gg@shellblade.net> | 2025-08-30 16:53:58 -0700 |
---|---|---|
committer | 3gg <3gg@shellblade.net> | 2025-08-30 16:53:58 -0700 |
commit | 6aaedb813fa11ba0679c3051bc2eb28646b9506c (patch) | |
tree | 34acbfc9840e02cb4753e6306ea7ce978bf8b58e /src/contrib/SDL-3.2.20/test/testlock.c | |
parent | 8f228ade99dd3d4c8da9b78ade1815c9adf85c8f (diff) |
Update to SDL3
Diffstat (limited to 'src/contrib/SDL-3.2.20/test/testlock.c')
-rw-r--r-- | src/contrib/SDL-3.2.20/test/testlock.c | 212 |
1 files changed, 212 insertions, 0 deletions
diff --git a/src/contrib/SDL-3.2.20/test/testlock.c b/src/contrib/SDL-3.2.20/test/testlock.c new file mode 100644 index 0000000..971b303 --- /dev/null +++ b/src/contrib/SDL-3.2.20/test/testlock.c | |||
@@ -0,0 +1,212 @@ | |||
1 | /* | ||
2 | Copyright (C) 1997-2025 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 <stdlib.h> /* for atexit() */ | ||
19 | |||
20 | #include <SDL3/SDL.h> | ||
21 | #include <SDL3/SDL_main.h> | ||
22 | #include <SDL3/SDL_test.h> | ||
23 | |||
24 | static SDL_Mutex *mutex = NULL; | ||
25 | static SDL_ThreadID mainthread; | ||
26 | static SDL_AtomicInt doterminate; | ||
27 | static int nb_threads = 6; | ||
28 | static SDL_Thread **threads; | ||
29 | static int worktime = 1000; | ||
30 | static SDLTest_CommonState *state; | ||
31 | |||
32 | /** | ||
33 | * SDL_Quit() shouldn't be used with atexit() directly because | ||
34 | * calling conventions may differ... | ||
35 | */ | ||
36 | static void | ||
37 | SDL_Quit_Wrapper(void) | ||
38 | { | ||
39 | SDL_Quit(); | ||
40 | SDLTest_CommonDestroyState(state); | ||
41 | } | ||
42 | |||
43 | static void printid(void) | ||
44 | { | ||
45 | SDL_Log("Thread %" SDL_PRIu64 ": exiting", SDL_GetCurrentThreadID()); | ||
46 | } | ||
47 | |||
48 | static void terminate(int sig) | ||
49 | { | ||
50 | (void)signal(SIGINT, terminate); | ||
51 | SDL_SetAtomicInt(&doterminate, 1); | ||
52 | } | ||
53 | |||
54 | static void closemutex(int sig) | ||
55 | { | ||
56 | SDL_ThreadID id = SDL_GetCurrentThreadID(); | ||
57 | int i; | ||
58 | SDL_Log("Thread %" SDL_PRIu64 ": Cleaning up...", id == mainthread ? 0 : id); | ||
59 | SDL_SetAtomicInt(&doterminate, 1); | ||
60 | if (threads) { | ||
61 | for (i = 0; i < nb_threads; ++i) { | ||
62 | SDL_WaitThread(threads[i], NULL); | ||
63 | } | ||
64 | SDL_free(threads); | ||
65 | threads = NULL; | ||
66 | } | ||
67 | SDL_DestroyMutex(mutex); | ||
68 | /* Let 'main()' return normally */ | ||
69 | if (sig != 0) { | ||
70 | exit(sig); | ||
71 | } | ||
72 | } | ||
73 | |||
74 | static int SDLCALL | ||
75 | Run(void *data) | ||
76 | { | ||
77 | SDL_ThreadID current_thread = SDL_GetCurrentThreadID(); | ||
78 | |||
79 | if (current_thread == mainthread) { | ||
80 | (void)signal(SIGTERM, closemutex); | ||
81 | } | ||
82 | SDL_Log("Thread %" SDL_PRIu64 ": starting up", current_thread); | ||
83 | while (!SDL_GetAtomicInt(&doterminate)) { | ||
84 | SDL_Log("Thread %" SDL_PRIu64 ": ready to work", current_thread); | ||
85 | SDL_LockMutex(mutex); | ||
86 | SDL_Log("Thread %" SDL_PRIu64 ": start work!", current_thread); | ||
87 | SDL_Delay(1 * worktime); | ||
88 | SDL_Log("Thread %" SDL_PRIu64 ": work done!", current_thread); | ||
89 | SDL_UnlockMutex(mutex); | ||
90 | |||
91 | /* If this sleep isn't done, then threads may starve */ | ||
92 | SDL_Delay(10); | ||
93 | } | ||
94 | if (current_thread == mainthread && SDL_GetAtomicInt(&doterminate)) { | ||
95 | SDL_Log("Thread %" SDL_PRIu64 ": raising SIGTERM", current_thread); | ||
96 | (void)raise(SIGTERM); | ||
97 | } | ||
98 | SDL_Log("Thread %" SDL_PRIu64 ": exiting!", current_thread); | ||
99 | return 0; | ||
100 | } | ||
101 | |||
102 | #ifndef _WIN32 | ||
103 | static Uint32 hit_timeout(void *param, SDL_TimerID timerID, Uint32 interval) { | ||
104 | SDL_Log("Hit timeout! Sending SIGINT!"); | ||
105 | (void)raise(SIGINT); | ||
106 | return 0; | ||
107 | } | ||
108 | #endif | ||
109 | |||
110 | int main(int argc, char *argv[]) | ||
111 | { | ||
112 | int i; | ||
113 | #ifndef _WIN32 | ||
114 | int timeout = 0; | ||
115 | #endif | ||
116 | |||
117 | /* Initialize test framework */ | ||
118 | state = SDLTest_CommonCreateState(argv, 0); | ||
119 | if (!state) { | ||
120 | return 1; | ||
121 | } | ||
122 | |||
123 | /* Parse commandline */ | ||
124 | for (i = 1; i < argc;) { | ||
125 | int consumed; | ||
126 | |||
127 | consumed = SDLTest_CommonArg(state, i); | ||
128 | if (!consumed) { | ||
129 | if (SDL_strcmp(argv[i], "--nbthreads") == 0) { | ||
130 | if (argv[i + 1]) { | ||
131 | char *endptr; | ||
132 | nb_threads = SDL_strtol(argv[i + 1], &endptr, 0); | ||
133 | if (endptr != argv[i + 1] && *endptr == '\0' && nb_threads > 0) { | ||
134 | consumed = 2; | ||
135 | } | ||
136 | } | ||
137 | } else if (SDL_strcmp(argv[i], "--worktime") == 0) { | ||
138 | if (argv[i + 1]) { | ||
139 | char *endptr; | ||
140 | nb_threads = SDL_strtol(argv[i + 1], &endptr, 0); | ||
141 | if (endptr != argv[i + 1] && *endptr == '\0' && nb_threads > 0) { | ||
142 | consumed = 2; | ||
143 | } | ||
144 | } | ||
145 | #ifndef _WIN32 | ||
146 | } else if (SDL_strcmp(argv[i], "--timeout") == 0) { | ||
147 | if (argv[i + 1]) { | ||
148 | char *endptr; | ||
149 | timeout = SDL_strtol(argv[i + 1], &endptr, 0); | ||
150 | if (endptr != argv[i + 1] && *endptr == '\0' && timeout > 0) { | ||
151 | consumed = 2; | ||
152 | } | ||
153 | } | ||
154 | #endif | ||
155 | } | ||
156 | } | ||
157 | if (consumed <= 0) { | ||
158 | static const char *options[] = { | ||
159 | "[--nbthreads NB]", | ||
160 | "[--worktime ms]", | ||
161 | #ifndef _WIN32 | ||
162 | "[--timeout ms]", | ||
163 | #endif | ||
164 | NULL, | ||
165 | }; | ||
166 | SDLTest_CommonLogUsage(state, argv[0], options); | ||
167 | exit(1); | ||
168 | } | ||
169 | |||
170 | i += consumed; | ||
171 | } | ||
172 | |||
173 | threads = SDL_malloc(nb_threads * sizeof(SDL_Thread*)); | ||
174 | |||
175 | /* Load the SDL library */ | ||
176 | if (!SDL_Init(0)) { | ||
177 | SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "%s", SDL_GetError()); | ||
178 | exit(1); | ||
179 | } | ||
180 | (void)atexit(SDL_Quit_Wrapper); | ||
181 | |||
182 | SDL_SetAtomicInt(&doterminate, 0); | ||
183 | |||
184 | mutex = SDL_CreateMutex(); | ||
185 | if (!mutex) { | ||
186 | SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create mutex: %s", SDL_GetError()); | ||
187 | exit(1); | ||
188 | } | ||
189 | |||
190 | mainthread = SDL_GetCurrentThreadID(); | ||
191 | SDL_Log("Main thread: %" SDL_PRIu64, mainthread); | ||
192 | (void)atexit(printid); | ||
193 | for (i = 0; i < nb_threads; ++i) { | ||
194 | char name[64]; | ||
195 | (void)SDL_snprintf(name, sizeof(name), "Worker%d", i); | ||
196 | threads[i] = SDL_CreateThread(Run, name, NULL); | ||
197 | if (threads[i] == NULL) { | ||
198 | SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create thread!"); | ||
199 | } | ||
200 | } | ||
201 | |||
202 | #ifndef _WIN32 | ||
203 | if (timeout) { | ||
204 | SDL_AddTimer(timeout, hit_timeout, NULL); | ||
205 | } | ||
206 | #endif | ||
207 | |||
208 | (void)signal(SIGINT, terminate); | ||
209 | Run(NULL); | ||
210 | |||
211 | return 0; /* Never reached */ | ||
212 | } | ||