UFO: Alien Invasion
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
threads.cpp
Go to the documentation of this file.
1 
5 /*
6 Copyright(c) 1997-2001 Id Software, Inc.
7 Copyright(c) 2002 The Quakeforge Project.
8 Copyright(c) 2006 Quake2World.
9 
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License
12 as published by the Free Software Foundation; either version 2
13 of the License, or(at your option) any later version.
14 
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18 
19 See the GNU General Public License for more details.
20 
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 
25 */
26 
27 #include "bsp.h"
28 #include "../../shared/thread.h"
29 
30 #define MAX_THREADS 8
31 
33 
37 static int GetThreadWork (void)
38 {
39  int r;
40  int f;
41 
42  ThreadLock();
43 
44  if (threadstate.workindex == threadstate.workcount) { /* done */
45  ThreadUnlock();
46  return -1;
47  }
48 
49  /* update work fraction and output progress if desired */
50  f = 10 * threadstate.workindex / threadstate.workcount;
51  if (f != threadstate.workfrac) {
52  threadstate.workfrac = f;
53  if (threadstate.progress) {
54  fprintf(stdout, "%i...", f);
55  fflush(stdout);
56  }
57  } else if (threadstate.progress && threadstate.workindex % threadstate.worktick == 0) {
58  fprintf(stdout, "%c\b", "-\\|/"[(threadstate.workindex / threadstate.worktick) & 3]);
59  fflush(stdout);
60  }
61 
62  /* assign the next work iteration */
63  r = threadstate.workindex;
64  threadstate.workindex++;
65 
66  ThreadUnlock();
67 
68  return r;
69 }
70 
71 
73 static void (*WorkFunction) (unsigned int);
74 
75 
80 static int ThreadWork (void* p)
81 {
82  while (true) {
83  int work = GetThreadWork();
84  if (work == -1)
85  break;
86  WorkFunction(work);
87  }
88 
89  return 0;
90 }
91 
92 
93 static SDL_mutex *lock = nullptr;
94 
95 static void ThreadInit (void)
96 {
97  if (lock != nullptr)
98  Sys_Error("Mutex already created!");
99 
100  lock = SDL_CreateMutex();
101 }
102 
103 static void ThreadRelease (void)
104 {
105  SDL_DestroyMutex(lock);
106  lock = nullptr;
107 }
108 
112 void ThreadLock (void)
113 {
114  if (threadstate.numthreads == 1) {
115  /* do nothing */
116  } else if (lock != nullptr && SDL_LockMutex(lock) != -1) {
117  /* already locked */
118  } else {
119  Sys_Error("Couldn't lock mutex (%p)!", (void*)lock);
120  }
121 }
122 
126 void ThreadUnlock (void)
127 {
128  if (threadstate.numthreads == 1) {
129  /* do nothing */
130  } else if (lock != nullptr && SDL_UnlockMutex(lock) != -1) {
131  /* already locked */
132  } else {
133  Sys_Error("Couldn't unlock mutex (%p)!", (void*)lock);
134  }
135 }
136 
137 static void RunThreads (void)
138 {
139  SDL_Thread *threads[MAX_THREADS];
140  int i;
141 
142  if (threadstate.numthreads == 1) {
143  ThreadWork(nullptr);
144  return;
145  }
146 
147  ThreadInit();
148 
149  for (i = 0; i < threadstate.numthreads; i++)
150  threads[i] = Com_CreateThread(ThreadWork, "CompileWorker");
151 
152  for (i = 0; i < threadstate.numthreads; i++)
153  SDL_WaitThread(threads[i], nullptr);
154 
155  ThreadRelease();
156 }
157 
158 
162 void RunThreadsOn (void (*func)(unsigned int), int unsigned workcount, bool progress, const char* id)
163 {
164  int start, end;
165 
166  if (threadstate.numthreads < 1) /* ensure safe thread counts */
167  threadstate.numthreads = 1;
168 
169  if (threadstate.numthreads > MAX_THREADS)
170  threadstate.numthreads = MAX_THREADS;
171 
172  threadstate.workindex = 0;
173  threadstate.workcount = workcount;
174  threadstate.workfrac = -1;
175  threadstate.progress = progress;
176  threadstate.worktick = sqrt(workcount) + 1;
177 
178  WorkFunction = func;
179 
180  start = time(nullptr);
181 
182  if (threadstate.progress) {
183  fprintf(stdout, "%10s: ", id);
184  fflush(stdout);
185  }
186 
187  RunThreads();
188 
189  end = time(nullptr);
190 
191  if (threadstate.progress) {
192  Verb_Printf(VERB_NORMAL, " (time: %6is, #: %i)\n", end - start, workcount);
193  }
194 }
195 
199 void RunSingleThreadOn (void (*func)(unsigned int), int unsigned workcount, bool progress, const char* id)
200 {
201  int saved_numthreads = threadstate.numthreads;
202 
203  threadstate.numthreads = 1;
204 
205  RunThreadsOn(func, workcount, progress, id);
206 
207  threadstate.numthreads = saved_numthreads;
208 }
#define MAX_THREADS
Definition: threads.cpp:30
void Sys_Error(const char *error,...)
Definition: g_main.cpp:421
static int GetThreadWork(void)
Return an iteration of work, updating progress when appropriate.
Definition: threads.cpp:37
void ThreadUnlock(void)
Release the lock on the shared data.
Definition: threads.cpp:126
static int ThreadWork(void *p)
Shared work entry point by all threads. Retrieve and perform chunks of work iteratively until work is...
Definition: threads.cpp:80
void RunThreadsOn(void(*func)(unsigned int), int unsigned workcount, bool progress, const char *id)
Entry point for all thread work requests.
Definition: threads.cpp:162
typedef int(ZCALLBACK *close_file_func) OF((voidpf opaque
SDL_Thread * Com_CreateThread(int(*fn)(void *), const char *name, void *data=nullptr)
Definition: thread.h:5
void ThreadLock(void)
Lock the shared data by the calling thread.
Definition: threads.cpp:112
threadstate_t threadstate
Definition: threads.cpp:32
void RunSingleThreadOn(void(*func)(unsigned int), int unsigned workcount, bool progress, const char *id)
Entry point for all thread work requests.
Definition: threads.cpp:199
threadstate_t
Definition: cl_renderer.h:209
void Verb_Printf(const verbosityLevel_t importance, const char *format,...) __attribute__((format(__printf__
static void ThreadRelease(void)
Definition: threads.cpp:103
const GLuint *typedef void(APIENTRY *GenRenderbuffersEXT_t)(GLsizei
Definition: r_gl.h:189
QGL_EXTERN GLfloat f
Definition: r_gl.h:114
static void(* WorkFunction)(unsigned int)
Generic function pointer to actual work to be done.
Definition: threads.cpp:73
QGL_EXTERN GLint i
Definition: r_gl.h:113
static void ThreadInit(void)
Definition: threads.cpp:95
static void RunThreads(void)
Definition: threads.cpp:137
static SDL_mutex * lock
Definition: threads.cpp:93