Richard Boegli's CnC_Generals_Zero_Hour Fork WIP
This is documentation of Richard Boegil's Zero Hour Fork
 
Loading...
Searching...
No Matches
critsec.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#include "critsec.h"
20#include <assert.h>
21#include "wlib/wdebug.h"
22
23
24
26{
27#ifdef _UNIX
28 pthread_mutex_init(&Mutex_, NULL);
29 RefCount_ = 0;
30#elif defined(_WIN32)
31 InitializeCriticalSection(&CritSec_);
32#endif
33}
34
36{
37 #ifdef _UNIX
38 pthread_mutex_destroy(&Mutex_);
39 #elif defined(_WIN32)
40 DeleteCriticalSection(&CritSec_);
41 #endif
42}
43
44// The "lock" function blocks until the mutex is available.
45// Returns 0 on success, error code on error.
46//
47// A thread that already has a lock will increment a reference count if it calls
48// lock again. It must then call unlock() enough times to get the reference to 0.
49//
50// If refcount is not null you can get the current ref counter after the lock.
51//
52sint32 CritSec::lock(int *refcount) RO
53{
54 #ifdef _UNIX
55 sint32 status;
56
57 // I TRY to get the lock. IF I succeed, OR if I fail because
58 // I already have the lock, I just increment the reference
59 // count and return.
60 if (((status = pthread_mutex_trylock(&Mutex_)) == 0) ||
61 ((status == EBUSY) && (ThreadId_ == pthread_self())))
62 {
63 ThreadId_ = pthread_self();
64 RefCount_++;
65 if (refcount)
66 *refcount=RefCount_;
67 return(0);
68 }
69
70 // Otherwise, I wait for the lock.
71 if ((status = pthread_mutex_lock(&Mutex_)) == 0)
72 {
73 assert(RefCount_ == 0);
74 ThreadId_ = pthread_self();
75 RefCount_++;
76 }
77 else
78 {
79 ERRMSG("pthread_mutex_lock: " << strerror(errno));
80 }
81
82 if (refcount)
83 *refcount=RefCount_;
84
85 return(status);
86 #elif defined(_WIN32)
87 // TOFIX update the refcount
88 EnterCriticalSection(&CritSec_);
89 return(0);
90 #else
91 #error Must define either _WIN32 or _UNIX
92 #endif
93}
94
95// The "unlock" function release the critical section.
97{
98 #ifdef _UNIX
99 sint32 status = 0;
100
101 assert(RefCount_ >= 0);
102 if (RefCount_ <= 0)
103 {
104 //ERRMSG("unlocking unlocked mutex!");
105 return(-1);
106 }
107
109 if (ThreadId_ != pthread_self())
110 {
111 WRNMSG("tried to unlock a mutex not owned by self");
112 return(-1);
113 }
114
115 if (--RefCount_ == 0)
116 {
117 // Set thread id to zero -- we're going to release mutex
118 ThreadId_ = (pthread_t)0;
119
120 // Unlock the mutex.
121 if ((status = pthread_mutex_unlock(&Mutex_)) != 0)
122 ERRMSG("pthread_mutex_lock: " << strerror(errno));
123 }
124 return status;
125 #elif defined(_WIN32)
126 LeaveCriticalSection(&CritSec_);
127 return(0);
128 #endif
129}
#define NULL
Definition BaseType.h:92
#define ERRMSG(X)
Definition wdebug.h:86
#define WRNMSG(X)
Definition wdebug.h:75
signed long sint32
Definition bittype.h:51
CritSec()
Definition critsec.cpp:25
sint32 unlock(void) RO
Definition critsec.cpp:96
pthread_mutex_t Mutex_
Definition critsec.h:56
sint32 lock(int *refcount=NULL) RO
Definition critsec.cpp:52
int RefCount_
Definition critsec.h:58
~CritSec()
Definition critsec.cpp:35
#define RO
Definition wstypes.h:92