Richard Boegli's CnC_Generals_Zero_Hour Fork WIP
This is documentation of Richard Boegil's Zero Hour Fork
 
Loading...
Searching...
No Matches
threadfac.cpp
Go to the documentation of this file.
1/*
2** Command & Conquer Generals Zero Hour(tm)
3** Copyright 2025 Electronic Arts Inc.
4**
5** This program is free software: you can redistribute it and/or modify
6** it under the terms of the GNU General Public License as published by
7** the Free Software Foundation, either version 3 of the License, or
8** (at your option) any later version.
9**
10** This program is distributed in the hope that it will be useful,
11** but WITHOUT ANY WARRANTY; without even the implied warranty of
12** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13** GNU General Public License for more details.
14**
15** You should have received a copy of the GNU General Public License
16** along with this program. If not, see <http://www.gnu.org/licenses/>.
17*/
18
19#define THREADFAC_CODE
20
21#include "threadfac.h"
22
23int Runnable::ThreadCount_ = 0;
24CritSec Runnable::CritSec_; // to protect ThreadCount_
25
26// MDC: Made all this dependent on _REENTRANT being defined so VC++ doesn't complain on
27// single-threaded programs...
28
29
30//
31// Note: I chose the following type signature for thread functions
32// void function(void *data);
33//
34//
35// Since Win32 & POSIX have different type signatures for the thread entry points
36// an intermediate system-dependent function in this file gets called first.
37// That function then calls the system independent version. So the system dependent
38// version needs 2 Items 1) The address of the _real_ thread func 2) the data
39// to pass. We only have 1 argument available, so you figure out the rest...
40//
41// This is for internal use only
42//
44{
45 void *startPoint; // The address of the _real_ thread function, or class
46 void *data; // data to pass to real thread function or class
47 bit8 destroy; // only applies to classes, should delete after execution?
48};
49
50
51
52//
53// Start a thread inside a class
54//
55bit8 ThreadFactory::startThread(Runnable &runable, void *data, bit8 destroy)
56{
57#ifdef _REENTRANT
58
59 {
60 Runnable::CritSec_.lock();
61 Runnable::ThreadCount_++;
62 Runnable::CritSec_.unlock();
63 }
64
65
67 tInfo->startPoint=(void *)&runable;
68 tInfo->data=data;
69 tInfo->destroy=destroy;
70
71 #ifdef _WIN32
72 // Under windows call _beginthreadex instead of CreateThread so you can
73 // use all the normal C library stuff. (IMPORTANT!!!)
74 uint32 handle;
75 uint32 stup1d;
76 handle=_beginthreadex(NULL,0, threadClassLauncher, tInfo, 0, &stup1d);
77 if (handle!=NULL)
78 return(TRUE);
79 else
80 {
81 {
82 runable.CritSec_.lock();
83 runable.ThreadCount_--; // Ok, so it didn't really start
84 runable.CritSec_.unlock();
85 }
86 return(FALSE);
87 }
88 #else // UNIX
89 // Setup thread attributes for client threads
90 int retval;
91 pthread_attr_t threadAttr;
92 pthread_attr_init(&threadAttr);
93 pthread_attr_setdetachstate(&threadAttr, PTHREAD_CREATE_DETACHED);
94 pthread_attr_setscope(&threadAttr,PTHREAD_SCOPE_SYSTEM);
95 retval=pthread_create(NULL,&threadAttr, threadClassLauncher, tInfo);
96 if (retval==0)
97 return(TRUE);
98 else
99 {
100 {
101 runable.CritSec_.lock();
102 runable.ThreadCount_--; // Ok, so it didn't really start
103 runable.CritSec_.unlock();
104 }
105 return(FALSE);
106 }
107 #endif
108#else
109 return (FALSE);
110#endif /* _REENTRANT */
111}
112
113
114//
115// Start a thread inside a function
116//
117bit8 ThreadFactory::startThread(void (*start_func)(void *), void *data)
118{
119#ifdef _REENTRANT
121 tInfo->startPoint=start_func;
122 tInfo->data=data;
123
124 #ifdef _WIN32
125 // Under windows call _beginthreadex instead of CreateThread so you can
126 // use all the normal C library stuff. (IMPORTANT!!!)
127 uint32 handle;
128 unsigned temp;
129 handle=_beginthreadex(NULL,0, threadFuncLauncher, tInfo, 0, &temp);
130 if (handle!=NULL)
131 return(TRUE);
132 return(FALSE);
133 #else // UNIX
134 // Setup thread attributes for client threads
135 int retval;
136 pthread_attr_t threadAttr;
137 pthread_attr_init(&threadAttr);
138 pthread_attr_setdetachstate(&threadAttr, PTHREAD_CREATE_DETACHED);
139 pthread_attr_setscope(&threadAttr,PTHREAD_SCOPE_SYSTEM);
140 retval=pthread_create(NULL,&threadAttr, threadFuncLauncher, tInfo);
141 if (retval==0)
142 return(TRUE);
143 else
144 return(FALSE);
145 #endif
146#else
147 return(FALSE);
148#endif /* REENTRANT */
149}
150
151#ifdef _WIN32
152 unsigned __stdcall threadFuncLauncher(void *temp)
153#else // UNIX
154 void *threadFuncLauncher(void *temp)
155#endif
156{
158
159 void (*start_func)(void *);
160 start_func=(void (*)(void *))tInfo->startPoint;
161
162 void *data=tInfo->data;
163 delete(tInfo);
164
165 start_func(data);
166 return(0);
167}
168
169#ifdef _WIN32
170 unsigned __stdcall threadClassLauncher(void *temp)
171#else // UNIX
172 void *threadClassLauncher(void *temp)
173#endif
174{
176
177 Runnable *thrClass=(Runnable *)tInfo->startPoint;
178 void *data=tInfo->data;
179 bit8 destroy=tInfo->destroy;
180 delete(tInfo);
181
182 thrClass->run(data);
183
184 if (destroy) // May want to free memory after thread finishes
185 delete(thrClass);
186
187 {
188 Runnable::CritSec_.lock();
189 Runnable::ThreadCount_--;
190 Runnable::CritSec_.unlock();
191 }
192
193 #ifdef _WIN32
194 ExitThread(0); // is this really needed?
195 #endif
196 return(0);
197}
198
201
204
205// Is there a thread running in this class
207{
208 // Don't need to lock a simple assignment
209 int temp=ThreadCount_;
210 return((temp>0)?TRUE:FALSE);
211}
212
213// How many threads are running in this class
215{
216 // Don't need to lock a simple assignment
217 int temp=ThreadCount_;
218 return(temp);
219}
220
221#undef THREADFAC_CODE
#define NULL
Definition BaseType.h:92
#define TRUE
Definition BaseType.h:109
#define FALSE
Definition BaseType.h:113
char bit8
Definition wstypes.h:61
unsigned long uint32
Definition bittype.h:46
sint32 unlock(void) RO
Definition critsec.cpp:96
sint32 lock(int *refcount=NULL) RO
Definition critsec.cpp:52
static int getThreadCount()
virtual ~Runnable()
virtual void run(void *data)=0
static bit8 isRunning(void)
static bit8 startThread(void(*start_func)(void *), void *data)
void * threadClassLauncher(void *temp)
void * threadFuncLauncher(void *temp)