You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
112 lines
2.3 KiB
112 lines
2.3 KiB
/** |
|
* @file dthread.cpp |
|
* |
|
* Implementation of functions for updating game state from network commands. |
|
*/ |
|
|
|
#include <list> |
|
#include <atomic> |
|
#include <mutex> |
|
|
|
#include "nthread.h" |
|
#include "utils/sdl_mutex.h" |
|
#include "utils/thread.h" |
|
|
|
namespace devilution { |
|
|
|
struct DThreadPkt { |
|
int pnum; |
|
_cmd_id cmd; |
|
std::unique_ptr<byte[]> data; |
|
uint32_t len; |
|
|
|
DThreadPkt(int pnum, _cmd_id(cmd), std::unique_ptr<byte[]> data, uint32_t len) |
|
: pnum(pnum) |
|
, cmd(cmd) |
|
, data(std::move(data)) |
|
, len(len) |
|
{ |
|
} |
|
}; |
|
|
|
namespace { |
|
|
|
SdlMutex DthreadMutex; |
|
SDL_threadID glpDThreadId; |
|
std::list<DThreadPkt> InfoList; |
|
std::atomic_bool dthread_running; |
|
event_emul *sghWorkToDoEvent; |
|
|
|
/* rdata */ |
|
SDL_Thread *sghThread = nullptr; |
|
|
|
void DthreadHandler() |
|
{ |
|
while (dthread_running) { |
|
if (InfoList.empty() && WaitForEvent(sghWorkToDoEvent) == -1) |
|
app_fatal("dthread4:\n%s", SDL_GetError()); |
|
|
|
DthreadMutex.lock(); |
|
if (InfoList.empty()) { |
|
ResetEvent(sghWorkToDoEvent); |
|
DthreadMutex.unlock(); |
|
continue; |
|
} |
|
DThreadPkt pkt = std::move(InfoList.front()); |
|
InfoList.pop_front(); |
|
DthreadMutex.unlock(); |
|
|
|
multi_send_zero_packet(pkt.pnum, pkt.cmd, pkt.data.get(), pkt.len); |
|
} |
|
} |
|
|
|
} // namespace |
|
|
|
void dthread_remove_player(uint8_t pnum) |
|
{ |
|
std::lock_guard<SdlMutex> lock(DthreadMutex); |
|
InfoList.remove_if([&](auto &pkt) { |
|
return pkt.pnum == pnum; |
|
}); |
|
} |
|
|
|
void dthread_send_delta(int pnum, _cmd_id cmd, std::unique_ptr<byte[]> data, uint32_t len) |
|
{ |
|
if (!gbIsMultiplayer) |
|
return; |
|
|
|
DThreadPkt pkt { pnum, cmd, std::move(data), len }; |
|
|
|
std::lock_guard<SdlMutex> lock(DthreadMutex); |
|
InfoList.push_back(std::move(pkt)); |
|
SetEvent(sghWorkToDoEvent); |
|
} |
|
|
|
void dthread_start() |
|
{ |
|
if (!gbIsMultiplayer) |
|
return; |
|
|
|
sghWorkToDoEvent = StartEvent(); |
|
dthread_running = true; |
|
sghThread = CreateThread(DthreadHandler, &glpDThreadId); |
|
} |
|
|
|
void DThreadCleanup() |
|
{ |
|
if (sghWorkToDoEvent == nullptr) |
|
return; |
|
|
|
dthread_running = false; |
|
SetEvent(sghWorkToDoEvent); |
|
if (sghThread != nullptr && glpDThreadId != SDL_GetThreadID(nullptr)) { |
|
SDL_WaitThread(sghThread, nullptr); |
|
sghThread = nullptr; |
|
} |
|
EndEvent(sghWorkToDoEvent); |
|
sghWorkToDoEvent = nullptr; |
|
|
|
InfoList.clear(); |
|
} |
|
|
|
} // namespace devilution
|
|
|