Skip to content

Commit 1f60c4d

Browse files
committed
xrCore: crc32 made thread safe
1 parent 764375a commit 1f60c4d

File tree

1 file changed

+53
-49
lines changed

1 file changed

+53
-49
lines changed

code/engine.vc2008/xrCore/crc32.cpp

Lines changed: 53 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,63 @@
11
#include "stdafx.h"
22
#pragma hdrstop
33

4-
static BOOL crc32_ready = FALSE;
54
static u32 crc32_table [256]; // Lookup table array
65

7-
inline u32 Reflect (u32 ref, char ch) // Reflects CRC bits in the lookup table
6+
class Crc32Initializer final
87
{
9-
// Used only by Init_CRC32_Table().
10-
11-
u32 value(0);
12-
13-
// Swap bit 0 for bit 7
14-
// bit 1 for bit 6, etc.
15-
for(int i = 1; i < (ch + 1); i++)
16-
{
17-
if(ref & 1)
18-
value |= 1 << (ch - i);
19-
ref >>= 1;
20-
}
21-
return value;
22-
}
23-
24-
void crc32_init ()
25-
{
26-
// Call this function only once to initialize the CRC table.
27-
28-
// This is the official polynomial used by CRC-32
29-
// in PKZip, WinZip and Ethernet.
30-
u32 ulPolynomial = 0x04c11db7;
31-
32-
// 256 values representing ASCII character codes.
33-
for(int i = 0; i <= 0xFF; i++)
34-
{
35-
crc32_table[i]=Reflect(i, 8) << 24;
36-
for (int j = 0; j < 8; j++)
37-
crc32_table[i] = (crc32_table[i] << 1) ^ (crc32_table[i] & (1 << 31) ? ulPolynomial : 0);
38-
crc32_table[i] = Reflect(crc32_table[i], 32);
39-
}
40-
}
8+
public:
9+
10+
static void init() noexcept
11+
{
12+
static Crc32Initializer initializer;
13+
}
14+
15+
private:
16+
17+
Crc32Initializer() noexcept
18+
{
19+
crc32_init();
20+
}
21+
22+
static u32 reflect(u32 ref, char ch) noexcept // Reflects CRC bits in the lookup table
23+
{
24+
// Used only by Init_CRC32_Table().
25+
26+
u32 value(0);
27+
28+
// Swap bit 0 for bit 7
29+
// bit 1 for bit 6, etc.
30+
for (int i = 1; i < (ch + 1); i++)
31+
{
32+
if (ref & 1)
33+
value |= 1 << (ch - i);
34+
ref >>= 1;
35+
}
36+
return value;
37+
}
38+
39+
static void crc32_init() noexcept
40+
{
41+
// Call this function only once to initialize the CRC table.
42+
43+
// This is the official polynomial used by CRC-32
44+
// in PKZip, WinZip and Ethernet.
45+
u32 ulPolynomial = 0x04c11db7;
46+
47+
// 256 values representing ASCII character codes.
48+
for (int i = 0; i <= 0xFF; i++)
49+
{
50+
crc32_table[i] = reflect(i, 8) << 24;
51+
for (int j = 0; j < 8; j++)
52+
crc32_table[i] = (crc32_table[i] << 1) ^ (crc32_table[i] & (1 << 31) ? ulPolynomial : 0);
53+
crc32_table[i] = reflect(crc32_table[i], 32);
54+
}
55+
}
56+
};
4157

4258
u32 crc32 (const void* P, u32 len)
4359
{
44-
if (!crc32_ready)
45-
{
46-
crc32_init ();
47-
crc32_ready = TRUE;
48-
}
60+
Crc32Initializer::init();
4961

5062
// Pass a text string to this function and it will return the CRC.
5163

@@ -71,11 +83,7 @@ u32 crc32 (const void* P, u32 len)
7183

7284
u32 crc32 (const void* P, u32 len, u32 starting_crc)
7385
{
74-
if (!crc32_ready)
75-
{
76-
crc32_init ();
77-
crc32_ready = TRUE;
78-
}
86+
Crc32Initializer::init();
7987

8088
u32 ulCRC = 0xffffffff ^ starting_crc;
8189
u8* buffer = (u8*)P;
@@ -88,11 +96,7 @@ u32 crc32 (const void* P, u32 len, u32 starting_crc)
8896

8997
u32 path_crc32 (const char* path, u32 len)
9098
{
91-
if (!crc32_ready)
92-
{
93-
crc32_init ();
94-
crc32_ready = TRUE;
95-
}
99+
Crc32Initializer::init();
96100

97101
u32 ulCRC = 0xffffffff;
98102
u8* buffer = (u8*)path;

0 commit comments

Comments
 (0)