mirror of
https://github.com/rehlds/rehlds.git
synced 2024-12-29 08:05:50 +03:00
Merge pull request #18 from dreamstalker/bits_write_rewrite
Fixed #17: Implemented faster and safe MSG_Write*Bit*
This commit is contained in:
commit
2cd9b7571c
@ -28,10 +28,6 @@
|
||||
|
||||
#include "precompiled.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
char serverinfo[MAX_INFO_STRING];
|
||||
|
||||
char gpszVersionString[32];
|
||||
@ -459,9 +455,29 @@ void MSG_WriteUsercmd(sizebuf_t *buf, usercmd_t *to, usercmd_t *from)
|
||||
|
||||
typedef struct bf_write_s
|
||||
{
|
||||
|
||||
//For enhanced and safe bits writing functions
|
||||
#if defined(REHLDS_OPT_PEDANTIC) || defined(REHLDS_FIXES)
|
||||
|
||||
#pragma pack(push, 1)
|
||||
union {
|
||||
uint64 u64;
|
||||
uint32 u32[2];
|
||||
uint8 u8[8];
|
||||
} pendingData;
|
||||
uint64 sse_highbits;
|
||||
#pragma pack(pop)
|
||||
|
||||
int nCurOutputBit;
|
||||
sizebuf_t *pbuf;
|
||||
|
||||
#else //defined(REHLDS_OPT_PEDANTIC) || defined(REHLDS_FIXES)
|
||||
|
||||
int nCurOutputBit;
|
||||
unsigned char *pOutByte;
|
||||
sizebuf_t *pbuf;
|
||||
|
||||
#endif //defined(REHLDS_OPT_PEDANTIC) || defined(REHLDS_FIXES)
|
||||
} bf_write_t;
|
||||
|
||||
typedef struct bf_read_s
|
||||
@ -476,7 +492,7 @@ typedef struct bf_read_s
|
||||
|
||||
// Bit field reading/writing storage.
|
||||
bf_read_t bfread;
|
||||
bf_write_t bfwrite;
|
||||
ALIGN16 bf_write_t bfwrite;
|
||||
|
||||
|
||||
void COM_BitOpsInit(void)
|
||||
@ -485,6 +501,68 @@ void COM_BitOpsInit(void)
|
||||
Q_memset(&bfread, 0, sizeof(bf_read_t));
|
||||
}
|
||||
|
||||
//Enhanced and safe bits writing functions
|
||||
#if defined(REHLDS_OPT_PEDANTIC) || defined(REHLDS_FIXES)
|
||||
|
||||
void MSG_WBits_MaybeFlush() {
|
||||
if (bfwrite.nCurOutputBit < 32)
|
||||
return;
|
||||
|
||||
uint32* pDest = (uint32*)SZ_GetSpace(bfwrite.pbuf, 4);
|
||||
if (!(bfwrite.pbuf->flags & SIZEBUF_OVERFLOWED))
|
||||
*pDest = bfwrite.pendingData.u32[0];
|
||||
|
||||
bfwrite.pendingData.u32[0] = bfwrite.pendingData.u32[1];
|
||||
bfwrite.pendingData.u32[1] = 0;
|
||||
bfwrite.nCurOutputBit -= 32;
|
||||
}
|
||||
|
||||
void MSG_WriteBits(uint32 data, int numbits)
|
||||
{
|
||||
uint32 maxval = _mm_cvtsi128_si32(_mm_slli_epi64(_mm_cvtsi32_si128(1), numbits)) - 1; //maxval = (1 << numbits) - 1
|
||||
if (data > maxval)
|
||||
data = maxval;
|
||||
|
||||
MSG_WBits_MaybeFlush();
|
||||
|
||||
__m128i pending = _mm_load_si128((__m128i*) &bfwrite.pendingData.u64);
|
||||
|
||||
__m128i mmdata = _mm_slli_epi64(_mm_cvtsi32_si128(data), bfwrite.nCurOutputBit); //mmdata = data << bfwrite.nCurOutputBit
|
||||
pending = _mm_or_si128(pending, mmdata);
|
||||
|
||||
_mm_store_si128((__m128i*) &bfwrite.pendingData.u64, pending);
|
||||
bfwrite.nCurOutputBit += numbits;
|
||||
}
|
||||
|
||||
void MSG_WriteOneBit(int nValue) {
|
||||
MSG_WriteBits(nValue, 1);
|
||||
}
|
||||
|
||||
void MSG_StartBitWriting(sizebuf_t *buf)
|
||||
{
|
||||
bfwrite.nCurOutputBit = 0;
|
||||
bfwrite.pbuf = buf;
|
||||
bfwrite.pendingData.u64 = 0;
|
||||
}
|
||||
|
||||
void MSG_EndBitWriting(sizebuf_t *buf)
|
||||
{
|
||||
int bytesNeed = bfwrite.nCurOutputBit / 8;
|
||||
if ((bfwrite.nCurOutputBit % 8) || bytesNeed == 0) {
|
||||
bytesNeed++;
|
||||
}
|
||||
|
||||
uint8* pData = (uint8*)SZ_GetSpace(bfwrite.pbuf, bytesNeed);
|
||||
if (!(bfwrite.pbuf->flags & SIZEBUF_OVERFLOWED)) {
|
||||
for (int i = 0; i < bytesNeed; i++) {
|
||||
pData[i] = bfwrite.pendingData.u8[i];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#else //defined(REHLDS_OPT_PEDANTIC) || defined(REHLDS_FIXES)
|
||||
|
||||
void MSG_WriteOneBit(int nValue)
|
||||
{
|
||||
if (bfwrite.nCurOutputBit >= 8)
|
||||
@ -582,6 +660,8 @@ void MSG_WriteBits(uint32 data, int numbits)
|
||||
}
|
||||
}
|
||||
|
||||
#endif //defined(REHLDS_OPT_PEDANTIC) || defined(REHLDS_FIXES)
|
||||
|
||||
void MSG_WriteSBits(int data, int numbits)
|
||||
{
|
||||
int idata = data;
|
||||
|
@ -1,17 +1,22 @@
|
||||
#include "precompiled.h"
|
||||
#include "cppunitlite/TestHarness.h"
|
||||
|
||||
TEST(BitsWritingReading, MSG, 5000)
|
||||
TEST(BitsWritingReading, MSG, 1000)
|
||||
{
|
||||
// TODO: Move to apropriate Init function
|
||||
int size = 4 * 1024 * 1024;
|
||||
Memory_Init(new char[size], size);
|
||||
SZ_Alloc("net_message", &net_message, 1024);
|
||||
byte localBuf[1024];
|
||||
|
||||
sizebuf_t *buf = &net_message;
|
||||
buf->buffername = "net_message";
|
||||
buf->data = localBuf;
|
||||
buf->maxsize = sizeof(localBuf);
|
||||
buf->cursize = 0;
|
||||
buf->flags = SIZEBUF_CHECK_OVERFLOW;
|
||||
|
||||
uint32 ff1 = ((uint32)1 << 31) - 1;
|
||||
uint32 ff2 = ((uint32)1 << 9) - 1;
|
||||
uint32 ff3 = 0xFFFFFFFF;
|
||||
|
||||
uint32 t1, t2, t3;
|
||||
|
||||
SZ_Clear(buf);
|
||||
|
||||
@ -23,8 +28,8 @@ TEST(BitsWritingReading, MSG, 5000)
|
||||
MSG_BeginReading();
|
||||
|
||||
MSG_StartBitReading(buf);
|
||||
uint32 t1 = MSG_ReadBits(31);
|
||||
uint32 t2 = MSG_ReadBits(9);
|
||||
t1 = MSG_ReadBits(31);
|
||||
t2 = MSG_ReadBits(9);
|
||||
MSG_EndBitReading(buf);
|
||||
|
||||
UINT32_EQUALS("31/9 Read failed (31)", ff1, t1);
|
||||
@ -49,6 +54,28 @@ TEST(BitsWritingReading, MSG, 5000)
|
||||
UINT32_EQUALS("9/31 Read failed (31)", ff2, t2);
|
||||
|
||||
|
||||
|
||||
SZ_Clear(buf);
|
||||
|
||||
MSG_StartBitWriting(buf);
|
||||
MSG_WriteBits(ff2, 9);
|
||||
MSG_WriteBits(ff3, 32);
|
||||
MSG_WriteBits(ff1, 31);
|
||||
MSG_EndBitWriting(buf);
|
||||
|
||||
MSG_BeginReading();
|
||||
|
||||
MSG_StartBitReading(buf);
|
||||
t2 = MSG_ReadBits(9);
|
||||
t3 = MSG_ReadBits(32);
|
||||
t1 = MSG_ReadBits(31);
|
||||
MSG_EndBitReading(buf);
|
||||
|
||||
UINT32_EQUALS("9/32/31 Read failed (9)", ff1, t1);
|
||||
UINT32_EQUALS("9/32/31 Read failed (32)", ff3, t3);
|
||||
UINT32_EQUALS("9/32/31 Read failed (31)", ff2, t2);
|
||||
|
||||
|
||||
uint32 a2, a1 = 5;
|
||||
uint32 b2, b1 = 0xEFEF;
|
||||
uint32 c2, c1 = 0x7AAEAEAE;
|
||||
@ -86,4 +113,37 @@ TEST(BitsWritingReading, MSG, 5000)
|
||||
UINT32_EQUALS("7/16/31 Read failed", a1, a2);
|
||||
UINT32_EQUALS("7/16/31 Read failed", b1, b2);
|
||||
UINT32_EQUALS("7/16/31 Read failed", c1, c2);
|
||||
|
||||
|
||||
SZ_Clear(buf);
|
||||
|
||||
MSG_StartBitWriting(buf);
|
||||
MSG_WriteBits(a1, 7);
|
||||
MSG_WriteBits(b1, 16);
|
||||
MSG_WriteBits(c1, 31);
|
||||
MSG_WriteBits(a1, 7);
|
||||
MSG_WriteBits(b1, 16);
|
||||
MSG_WriteBits(c1, 31);
|
||||
|
||||
MSG_EndBitWriting(buf);
|
||||
|
||||
MSG_BeginReading();
|
||||
|
||||
MSG_StartBitReading(buf);
|
||||
a2 = MSG_ReadBits(7);
|
||||
b2 = MSG_ReadBits(16);
|
||||
c2 = MSG_ReadBits(31);
|
||||
UINT32_EQUALS("7/16/31 Read failed", a1, a2);
|
||||
UINT32_EQUALS("7/16/31 Read failed", b1, b2);
|
||||
UINT32_EQUALS("7/16/31 Read failed", c1, c2);
|
||||
|
||||
a2 = MSG_ReadBits(7);
|
||||
b2 = MSG_ReadBits(16);
|
||||
c2 = MSG_ReadBits(31);
|
||||
UINT32_EQUALS("7/16/31 Read failed", a1, a2);
|
||||
UINT32_EQUALS("7/16/31 Read failed", b1, b2);
|
||||
UINT32_EQUALS("7/16/31 Read failed", c1, c2);
|
||||
|
||||
MSG_EndBitReading(buf);
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user