Browse Source

Remove threading from miniwin

pull/606/head
Anders Jenbo 6 years ago
parent
commit
c26fa8fa3f
  1. 19
      3rdParty/Storm/Source/storm.h
  2. 2
      CMakeLists.txt
  3. 4
      Source/appfat.cpp
  4. 24
      Source/diablo.cpp
  5. 26
      Source/dthread.cpp
  6. 2
      Source/dthread.h
  7. 2
      Source/effects.cpp
  8. 20
      Source/nthread.cpp
  9. 2
      Source/nthread.h
  10. 6
      Source/pfile.cpp
  11. 1
      SourceS/miniwin.h
  12. 14
      SourceS/miniwin/misc.h
  13. 25
      SourceS/miniwin/misc_macro.h
  14. 11
      SourceS/miniwin/thread.h
  15. 2
      SourceS/sdl2_to_1_2_backports.h
  16. 17
      SourceS/thread.h
  17. 176
      SourceX/miniwin/thread.cpp
  18. 78
      SourceX/thread.cpp
  19. 1
      types.h

19
3rdParty/Storm/Source/storm.h vendored

@ -14,26 +14,31 @@ extern std::string basePath;
#endif
#ifdef __cplusplus
//static float infinity = std::numeric_limits<float>::infinity();
struct CCritSect {
CRITICAL_SECTION m_critsect;
SDL_mutex *m_critsect;
CCritSect()
{
InitializeCriticalSection(&m_critsect);
m_critsect = SDL_CreateMutex();
if (m_critsect == NULL) {
ErrSdl();
}
}
~CCritSect()
{
DeleteCriticalSection(&m_critsect);
SDL_DestroyMutex(m_critsect);
}
void Enter()
{
EnterCriticalSection(&m_critsect);
if (SDL_LockMutex(m_critsect) < 0) {
ErrSdl();
}
}
void Leave()
{
LeaveCriticalSection(&m_critsect);
if (SDL_UnlockMutex(m_critsect) < 0) {
ErrSdl();
}
}
};
#endif

2
CMakeLists.txt

@ -257,7 +257,7 @@ set(devilutionx_SRCS
SourceX/controls/touch.cpp
SourceX/display.cpp
SourceX/miniwin/misc_msg.cpp
SourceX/miniwin/thread.cpp
SourceX/thread.cpp
SourceX/sound.cpp
SourceX/soundsample.cpp
SourceX/storm/storm.cpp

4
Source/appfat.cpp

@ -34,11 +34,11 @@ void MsgBox(const char *pszFmt, va_list va)
void FreeDlg()
{
if (terminating && cleanup_thread_id != GetCurrentThreadId())
if (terminating && cleanup_thread_id != SDL_GetThreadID(NULL))
SDL_Delay(20000);
terminating = TRUE;
cleanup_thread_id = GetCurrentThreadId();
cleanup_thread_id = SDL_GetThreadID(NULL);
if (gbMaxPlayers > 1) {
if (SNetLeaveGame(3))

24
Source/diablo.cpp

@ -460,6 +460,12 @@ BOOL PressEscKey()
return rv;
}
static void GetMousePos(LPARAM lParam)
{
MouseX = (short)(lParam & 0xffff);
MouseY = (short)((lParam >> 16) & 0xffff);
}
LRESULT DisableInputWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg) {
@ -469,8 +475,7 @@ LRESULT DisableInputWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
case WM_SYSKEYDOWN:
case WM_SYSCOMMAND:
case WM_MOUSEMOVE:
MouseX = (short)LOWORD(lParam);
MouseY = (short)HIWORD(lParam);
GetMousePos(lParam);
return 0;
case WM_LBUTTONDOWN:
if (sgbMouseDown != 0)
@ -526,21 +531,18 @@ LRESULT GM_Game(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
}
break;
case WM_MOUSEMOVE:
MouseX = (short)LOWORD(lParam);
MouseY = (short)HIWORD(lParam);
GetMousePos(lParam);
gmenu_on_mouse_move();
return 0;
case WM_LBUTTONDOWN:
MouseX = (short)LOWORD(lParam);
MouseY = (short)HIWORD(lParam);
GetMousePos(lParam);
if (sgbMouseDown == 0) {
sgbMouseDown = 1;
track_repeat_walk(LeftMouseDown(wParam));
}
return 0;
case WM_LBUTTONUP:
MouseX = (short)LOWORD(lParam);
MouseY = (short)HIWORD(lParam);
GetMousePos(lParam);
if (sgbMouseDown == 1) {
sgbMouseDown = 0;
LeftMouseUp();
@ -548,16 +550,14 @@ LRESULT GM_Game(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
}
return 0;
case WM_RBUTTONDOWN:
MouseX = (short)LOWORD(lParam);
MouseY = (short)HIWORD(lParam);
GetMousePos(lParam);
if (sgbMouseDown == 0) {
sgbMouseDown = 2;
RightMouseDown();
}
return 0;
case WM_RBUTTONUP:
MouseX = (short)LOWORD(lParam);
MouseY = (short)HIWORD(lParam);
GetMousePos(lParam);
if (sgbMouseDown == 2) {
sgbMouseDown = 0;
}

26
Source/dthread.cpp

@ -4,13 +4,13 @@
DEVILUTION_BEGIN_NAMESPACE
static CCritSect sgMemCrit;
unsigned int glpDThreadId;
SDL_threadID glpDThreadId;
TMegaPkt *sgpInfoHead; /* may not be right struct */
BOOLEAN dthread_running;
HANDLE sghWorkToDoEvent;
event_emul *sghWorkToDoEvent;
/* rdata */
static HANDLE sghThread = INVALID_HANDLE_VALUE;
static SDL_Thread *sghThread = NULL;
void dthread_remove_player(int pnum)
{
@ -58,7 +58,7 @@ void dthread_start()
return;
}
sghWorkToDoEvent = CreateEvent();
sghWorkToDoEvent = StartEvent();
if (!sghWorkToDoEvent) {
error_buf = TraceLastError();
app_fatal("dthread:1\n%s", error_buf);
@ -66,8 +66,8 @@ void dthread_start()
dthread_running = TRUE;
sghThread = (HANDLE)_beginthreadex(NULL, 0, dthread_handler, NULL, 0, &glpDThreadId);
if (sghThread == INVALID_HANDLE_VALUE) {
sghThread = CreateThread(dthread_handler, &glpDThreadId);
if (sghThread == NULL) {
error_buf = TraceLastError();
app_fatal("dthread2:\n%s", error_buf);
}
@ -80,7 +80,7 @@ unsigned int dthread_handler(void *)
DWORD dwMilliseconds;
while (dthread_running) {
if (!sgpInfoHead && WaitForSingleObject(sghWorkToDoEvent, 0xFFFFFFFF) == -1) {
if (!sgpInfoHead && WaitForEvent(sghWorkToDoEvent) == -1) {
error_buf = TraceLastError();
app_fatal("dthread4:\n%s", error_buf);
}
@ -122,15 +122,11 @@ void dthread_cleanup()
dthread_running = FALSE;
SetEvent(sghWorkToDoEvent);
if (sghThread != INVALID_HANDLE_VALUE && glpDThreadId != GetCurrentThreadId()) {
if (WaitForSingleObject(sghThread, 0xFFFFFFFF) == -1) {
error_buf = TraceLastError();
app_fatal("dthread3:\n(%s)", error_buf);
}
CloseEvent(sghThread);
sghThread = INVALID_HANDLE_VALUE;
if (sghThread != NULL && glpDThreadId != SDL_GetThreadID(NULL)) {
SDL_WaitThread(sghThread, NULL);
sghThread = NULL;
}
CloseEvent(sghWorkToDoEvent);
EndEvent(sghWorkToDoEvent);
sghWorkToDoEvent = NULL;
while (sgpInfoHead) {

2
Source/dthread.h

@ -2,7 +2,7 @@
#ifndef __DTHREAD_H__
#define __DTHREAD_H__
extern unsigned int glpDThreadId;
extern SDL_threadID glpDThreadId;
extern BOOLEAN dthread_running;
void dthread_remove_player(int pnum);

2
Source/effects.cpp

@ -1242,7 +1242,7 @@ void effects_play_sound(char *snd_file)
}
for (i = 0; i < sizeof(sgSFX) / sizeof(TSFX); i++) {
if (!_strcmpi(sgSFX[i].pszName, snd_file) && sgSFX[i].pSnd) {
if (!strcasecmp(sgSFX[i].pszName, snd_file) && sgSFX[i].pSnd) {
if (!snd_playing(sgSFX[i].pSnd))
snd_play_snd(sgSFX[i].pSnd, 0, 0);

20
Source/nthread.cpp

@ -10,7 +10,7 @@ DWORD gdwDeltaBytesSec;
BOOLEAN nthread_should_run;
DWORD gdwTurnsInTransit;
uintptr_t glpMsgTbl[MAX_PLRS];
unsigned int glpNThreadId;
SDL_threadID glpNThreadId;
char sgbSyncCountdown;
int turn_upper_bit;
BOOLEAN sgbTicsOutOfSync;
@ -21,7 +21,7 @@ DWORD gdwNormalMsgSize;
int last_tick;
/* data */
static HANDLE sghThread = INVALID_HANDLE_VALUE;
static SDL_Thread *sghThread = NULL;
void nthread_terminate_game(const char *pszFcn)
{
@ -157,12 +157,11 @@ void nthread_start(BOOL set_turn_upper_bit)
sgbThreadIsRunning = FALSE;
sgMemCrit.Enter();
nthread_should_run = TRUE;
sghThread = (HANDLE)_beginthreadex(NULL, 0, nthread_handler, NULL, 0, &glpNThreadId);
if (sghThread == INVALID_HANDLE_VALUE) {
sghThread = CreateThread(nthread_handler, &glpNThreadId);
if (sghThread == NULL) {
err2 = TraceLastError();
app_fatal("nthread2:\n%s", err2);
}
SetThreadPriority(sghThread, THREAD_PRIORITY_HIGHEST);
}
}
@ -198,20 +197,17 @@ void nthread_cleanup()
gdwTurnsInTransit = 0;
gdwNormalMsgSize = 0;
gdwLargestMsgSize = 0;
if (sghThread != INVALID_HANDLE_VALUE && glpNThreadId != GetCurrentThreadId()) {
if (sghThread != NULL && glpNThreadId != SDL_GetThreadID(NULL)) {
if (!sgbThreadIsRunning)
sgMemCrit.Leave();
if (WaitForSingleObject(sghThread, 0xFFFFFFFF) == -1) {
app_fatal("nthread3:\n(%s)", TraceLastError());
}
CloseEvent(sghThread);
sghThread = INVALID_HANDLE_VALUE;
SDL_WaitThread(sghThread, NULL);
sghThread = NULL;
}
}
void nthread_ignore_mutex(BOOL bStart)
{
if (sghThread != INVALID_HANDLE_VALUE) {
if (sghThread != NULL) {
if (bStart)
sgMemCrit.Leave();
else

2
Source/nthread.h

@ -8,7 +8,7 @@ extern DWORD gdwDeltaBytesSec;
extern BOOLEAN nthread_should_run;
extern DWORD gdwTurnsInTransit;
extern uintptr_t glpMsgTbl[MAX_PLRS];
extern unsigned int glpNThreadId;
extern SDL_threadID glpNThreadId;
extern int turn_upper_bit;
extern BOOLEAN sgbThreadIsRunning;
extern DWORD gdwLargestMsgSize;

6
Source/pfile.cpp

@ -34,7 +34,7 @@ DWORD pfile_get_save_num_from_name(const char *name)
DWORD i;
for (i = 0; i < MAX_CHARACTERS; i++) {
if (!_strcmpi(hero_names[i], name))
if (!strcasecmp(hero_names[i], name))
break;
}
@ -124,7 +124,7 @@ BOOL pfile_rename_hero(const char *name_1, const char *name_2)
if (pfile_get_save_num_from_name(name_2) == MAX_CHARACTERS) {
for (i = 0; i != MAX_PLRS; i++) {
if (!_strcmpi(name_1, plr[i]._pName)) {
if (!strcasecmp(name_1, plr[i]._pName)) {
found = TRUE;
break;
}
@ -139,7 +139,7 @@ BOOL pfile_rename_hero(const char *name_1, const char *name_2)
SStrCopy(hero_names[save_num], name_2, PLR_NAME_LEN);
SStrCopy(plr[i]._pName, name_2, PLR_NAME_LEN);
if (!_strcmpi(gszHero, name_1))
if (!strcasecmp(gszHero, name_1))
SStrCopy(gszHero, name_2, sizeof(gszHero));
game_2_ui_player(plr, &uihero, gbValidSaveFile);
UiSetupPlayerInfo(gszHero, &uihero, GAME_ID);

1
SourceS/miniwin.h

@ -22,7 +22,6 @@
#endif
#include "miniwin/misc.h"
#include "miniwin/thread.h"
#include "storm_full.h"
#ifndef MAX_PATH

14
SourceS/miniwin/misc.h

@ -20,8 +20,6 @@ typedef void *PVOID;
typedef unsigned int UINT;
typedef uintptr_t DWORD_PTR, *PDWORD_PTR;
typedef uintptr_t WPARAM;
typedef uintptr_t LPARAM;
typedef uintptr_t LRESULT;
@ -50,12 +48,6 @@ typedef struct tagMSG {
// Everything else
//
HANDLE CreateEventA();
BOOL CloseEvent(HANDLE event);
void SetEvent(HANDLE hEvent);
void ResetEvent(HANDLE hEvent);
int WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds);
void SetCursorPos(int X, int Y);
void FocusOnCharInfo();
@ -67,11 +59,6 @@ bool TranslateMessage(const MSG *lpMsg);
LRESULT DispatchMessageA(const MSG *lpMsg);
bool PostMessageA(UINT Msg, WPARAM wParam, LPARAM lParam);
uintptr_t DVL_beginthreadex(void *_Security, unsigned _StackSize, unsigned(*_StartAddress)(void *),
void *_ArgList, unsigned _InitFlag, unsigned *_ThrdAddr);
DWORD GetCurrentThreadId();
bool SetThreadPriority(HANDLE hThread, int nPriority);
//
// MSCVRT emulation
//
@ -79,7 +66,6 @@ bool SetThreadPriority(HANDLE hThread, int nPriority);
constexpr auto DVL_FILE_CURRENT = 1;
constexpr auto DVL_WM_QUIT = 0x0012;
constexpr auto DVL_INFINITE = 0xFFFFFFFF;
//
// Events

25
SourceS/miniwin/misc_macro.h

@ -3,44 +3,21 @@
#define TRUE true
#define FALSE false
#define INVALID_HANDLE_VALUE ((HANDLE)-1)
#define INVALID_HANDLE ((HANDLE)-1)
//
// Intrinsics
//
#define LOWORD(l) ((WORD)(((DWORD_PTR)(l)) & 0xffff))
#define HIWORD(l) ((WORD)((((DWORD_PTR)(l)) >> 16) & 0xffff))
#define CreateEvent CreateEventA
#define WM_QUIT DVL_WM_QUIT
#define PeekMessage PeekMessageA
#define DispatchMessage DispatchMessageA
#define PostMessage PostMessageA
#define _strcmpi(a, b) strcasecmp(a, b)
#define THREAD_PRIORITY_HIGHEST 2
//
// File I/O
//
#define FILE_CURRENT DVL_FILE_CURRENT
//
// Calculate the byte offset of a field in a structure of type type.
//
#define DeleteFile DeleteFileA
//
// Events
//
#define _beginthreadex DVL_beginthreadex
#define WM_QUIT DVL_WM_QUIT
#define WM_MOUSEMOVE DVL_WM_MOUSEMOVE
#define WM_LBUTTONDOWN DVL_WM_LBUTTONDOWN

11
SourceS/miniwin/thread.h

@ -1,11 +0,0 @@
#pragma once
namespace dvl {
typedef void *CRITICAL_SECTION, **LPCRITICAL_SECTION;
void InitializeCriticalSection(LPCRITICAL_SECTION lpCriticalSection);
void EnterCriticalSection(LPCRITICAL_SECTION lpCriticalSection);
void LeaveCriticalSection(LPCRITICAL_SECTION lpCriticalSection);
void DeleteCriticalSection(LPCRITICAL_SECTION lpCriticalSection);
} // namespace dvl

2
SourceS/sdl2_to_1_2_backports.h

@ -21,6 +21,8 @@
//== Events handling
#define SDL_threadID Uint32
#define SDL_Keysym SDL_keysym
#define SDL_Keycode SDLKey

17
SourceS/thread.h

@ -0,0 +1,17 @@
#pragma once
namespace dvl {
typedef struct event_emul {
SDL_mutex *mutex;
SDL_cond *cond;
} event_emul;
event_emul *StartEvent();
void EndEvent(event_emul *event);
void SetEvent(event_emul *e);
void ResetEvent(event_emul *e);
int WaitForEvent(event_emul *e);
SDL_Thread *CreateThread(unsigned int (*handler)(void *), SDL_threadID *ThreadID);
} // namespace dvl

176
SourceX/miniwin/thread.cpp

@ -1,176 +0,0 @@
#include "devilution.h"
#include "stubs.h"
#include <SDL.h>
#include <set>
namespace dvl {
static std::set<uintptr_t> threads;
static std::set<uintptr_t> events;
struct event_emul {
SDL_mutex *mutex;
SDL_cond *cond;
};
struct func_translate {
unsigned int (*func)(void *);
void *arg;
};
static int SDLCALL thread_translate(void *ptr)
{
func_translate *ftptr = static_cast<func_translate *>(ptr);
auto ret = ftptr->func(ftptr->arg);
delete ftptr;
return ret;
}
uintptr_t DVL_beginthreadex(void *_Security, unsigned _StackSize, unsigned (*_StartAddress)(void *),
void *_ArgList, unsigned _InitFlag, unsigned *_ThrdAddr)
{
if (_Security != NULL)
UNIMPLEMENTED();
if (_StackSize != 0)
UNIMPLEMENTED();
if (_InitFlag != 0)
UNIMPLEMENTED();
func_translate *ft = new func_translate;
ft->func = _StartAddress;
ft->arg = _ArgList;
#ifdef USE_SDL1
SDL_Thread *ret = SDL_CreateThread(thread_translate, ft);
#else
SDL_Thread *ret = SDL_CreateThread(thread_translate, NULL, ft);
#endif
if (ret == NULL) {
ErrSdl();
}
*_ThrdAddr = SDL_GetThreadID(ret);
threads.insert((uintptr_t)ret);
return (uintptr_t)ret;
}
DWORD GetCurrentThreadId()
{
// DWORD is compatible with SDL_threadID
return SDL_GetThreadID(NULL);
}
bool SetThreadPriority(HANDLE hThread, int nPriority)
{
// SDL cannot set the priority of the non-current thread
// (and e.g. unprivileged processes on Linux cannot increase it)
return true;
}
void InitializeCriticalSection(LPCRITICAL_SECTION lpCriticalSection)
{
SDL_mutex *m = SDL_CreateMutex();
if (m == NULL) {
ErrSdl();
}
*lpCriticalSection = m;
}
void EnterCriticalSection(LPCRITICAL_SECTION lpCriticalSection)
{
if (SDL_LockMutex(*((SDL_mutex **)lpCriticalSection)) <= -1) {
ErrSdl();
}
}
void LeaveCriticalSection(LPCRITICAL_SECTION lpCriticalSection)
{
if (SDL_UnlockMutex(*((SDL_mutex **)lpCriticalSection)) <= -1) {
ErrSdl();
}
}
void DeleteCriticalSection(LPCRITICAL_SECTION lpCriticalSection)
{
SDL_DestroyMutex(*((SDL_mutex **)lpCriticalSection));
}
HANDLE CreateEventA()
{
struct event_emul *ret;
ret = (struct event_emul *)malloc(sizeof(struct event_emul));
ret->mutex = SDL_CreateMutex();
if (ret->mutex == NULL) {
ErrSdl();
}
ret->cond = SDL_CreateCond();
if (ret->cond == NULL) {
ErrSdl();
}
events.insert((uintptr_t)ret);
return ret;
}
BOOL CloseEvent(HANDLE hObject)
{
struct event_emul *event = static_cast<struct event_emul *>(hObject);
if (events.find((uintptr_t)event) == events.end())
return false;
SDL_DestroyCond(event->cond);
SDL_DestroyMutex(event->mutex);
events.erase((uintptr_t)event);
free(event);
return true;
}
void SetEvent(HANDLE hEvent)
{
struct event_emul *e = (struct event_emul *)hEvent;
if (SDL_LockMutex(e->mutex) <= -1 || SDL_CondSignal(e->cond) <= -1 || SDL_UnlockMutex(e->mutex) <= -1) {
ErrSdl();
}
}
void ResetEvent(HANDLE hEvent)
{
struct event_emul *e = (struct event_emul *)hEvent;
if (SDL_LockMutex(e->mutex) <= -1 || SDL_CondWaitTimeout(e->cond, e->mutex, 0) <= -1 || SDL_UnlockMutex(e->mutex) <= -1) {
ErrSdl();
}
}
static int wait_for_sdl_cond(HANDLE hHandle, DWORD dwMilliseconds)
{
struct event_emul *e = (struct event_emul *)hHandle;
if (SDL_LockMutex(e->mutex) <= -1) {
ErrSdl();
}
int ret;
if (dwMilliseconds == DVL_INFINITE)
ret = SDL_CondWait(e->cond, e->mutex);
else
ret = SDL_CondWaitTimeout(e->cond, e->mutex, dwMilliseconds);
if (ret <= -1 || SDL_CondSignal(e->cond) <= -1 || SDL_UnlockMutex(e->mutex) <= -1) {
SDL_Log(SDL_GetError());
return -1;
}
return ret;
}
static int wait_for_sdl_thread(HANDLE hHandle, DWORD dwMilliseconds)
{
if (dwMilliseconds != DVL_INFINITE)
UNIMPLEMENTED();
SDL_Thread *t = (SDL_Thread *)hHandle;
SDL_WaitThread(t, NULL);
return 0;
}
int WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds)
{
// return value different from WinAPI
if (threads.find((uintptr_t)hHandle) != threads.end())
return wait_for_sdl_thread(hHandle, dwMilliseconds);
if (events.find((uintptr_t)hHandle) != events.end())
return wait_for_sdl_cond(hHandle, dwMilliseconds);
UNIMPLEMENTED();
}
}

78
SourceX/thread.cpp

@ -0,0 +1,78 @@
#include "devilution.h"
#include "stubs.h"
#include <SDL.h>
#include <set>
namespace dvl {
static int SDLCALL thread_translate(void *ptr)
{
unsigned int (*handler)(void *) = (unsigned int (*)(void *))ptr;
return handler(NULL);
}
SDL_Thread *CreateThread(unsigned int (*handler)(void *), SDL_threadID *ThreadID)
{
#ifdef USE_SDL1
SDL_Thread *ret = SDL_CreateThread(thread_translate, (void *)handler);
#else
SDL_Thread *ret = SDL_CreateThread(thread_translate, NULL, (void *)handler);
#endif
if (ret == NULL) {
ErrSdl();
}
*ThreadID = SDL_GetThreadID(ret);
return ret;
}
event_emul *StartEvent()
{
event_emul *ret;
ret = (event_emul *)malloc(sizeof(event_emul));
ret->mutex = SDL_CreateMutex();
if (ret->mutex == NULL) {
ErrSdl();
}
ret->cond = SDL_CreateCond();
if (ret->cond == NULL) {
ErrSdl();
}
return ret;
}
void EndEvent(event_emul *event)
{
SDL_DestroyCond(event->cond);
SDL_DestroyMutex(event->mutex);
free(event);
}
void SetEvent(event_emul *e)
{
if (SDL_LockMutex(e->mutex) <= -1 || SDL_CondSignal(e->cond) <= -1 || SDL_UnlockMutex(e->mutex) <= -1) {
ErrSdl();
}
}
void ResetEvent(event_emul *e)
{
if (SDL_LockMutex(e->mutex) <= -1 || SDL_CondWaitTimeout(e->cond, e->mutex, 0) <= -1 || SDL_UnlockMutex(e->mutex) <= -1) {
ErrSdl();
}
}
int WaitForEvent(event_emul *e)
{
if (SDL_LockMutex(e->mutex) <= -1) {
ErrSdl();
}
int ret = SDL_CondWait(e->cond, e->mutex);
if (ret <= -1 || SDL_CondSignal(e->cond) <= -1 || SDL_UnlockMutex(e->mutex) <= -1) {
SDL_Log(SDL_GetError());
return -1;
}
return ret;
}
}

1
types.h

@ -10,6 +10,7 @@
#include "miniwin.h"
#include "soundsample.h"
#include "thread.h"
#include "ui_fwd.h"
DEVILUTION_BEGIN_NAMESPACE

Loading…
Cancel
Save