Multithread the exec command #115
No files matched your search
@@ -462,6 +462,7 @@ DBGNAME?=$(EXENAME).debug
|
||||
OBJS:=$(i_main_o) \
|
||||
$(OBJDIR)/comptime.o \
|
||||
$(OBJDIR)/string.o \
|
||||
$(OBJDIR)/d_async.o \
|
||||
$(OBJDIR)/d_main.o \
|
||||
$(OBJDIR)/d_protocol.o \
|
||||
$(OBJDIR)/d_clisrv.o \
|
||||
|
||||
+79
-28
@@ -18,6 +18,7 @@
|
||||
|
||||
#include "doomdef.h"
|
||||
#include "doomstat.h"
|
||||
#include "d_main.h"
|
||||
#include "command.h"
|
||||
#include "console.h"
|
||||
#include "z_zone.h"
|
||||
@@ -34,6 +35,8 @@
|
||||
#include "p_setup.h"
|
||||
#include "lua_script.h"
|
||||
#include "d_netfil.h" // findfile
|
||||
#include "d_async.h"
|
||||
#include "filesrch.h"
|
||||
|
||||
//========
|
||||
// protos.
|
||||
@@ -121,11 +124,9 @@ void COM_BufAddText(const char *ptext)
|
||||
l = strlen(ptext);
|
||||
|
||||
if (com_text.cursize + l >= com_text.maxsize)
|
||||
{
|
||||
CONS_Alert(CONS_WARNING, M_GetText("Command buffer full!\n"));
|
||||
return;
|
||||
}
|
||||
VS_Write(&com_text, ptext, l);
|
||||
else
|
||||
VS_Write(&com_text, ptext, l);
|
||||
}
|
||||
|
||||
/** Adds command text and executes it immediately.
|
||||
@@ -752,12 +753,60 @@ static void COM_CEchoDuration_f(void)
|
||||
HU_SetCEchoDuration(atoi(COM_Argv(1)));
|
||||
}
|
||||
|
||||
struct COM_Exec_Ctx
|
||||
{
|
||||
boolean noerror;
|
||||
boolean silent;
|
||||
UINT8 * buf;
|
||||
};
|
||||
|
||||
static void Free_COM_Exec_Ctx (struct COM_Exec_Ctx *ctx)
|
||||
{
|
||||
Z_Free(ctx->buf);
|
||||
Z_Free(ctx);
|
||||
}
|
||||
|
||||
void COM_ExecuteFile (void *p, void *u)
|
||||
{
|
||||
filequery_t * q = p;
|
||||
struct COM_Exec_Ctx * ctx = u;
|
||||
|
||||
ctx->buf = NULL;
|
||||
|
||||
if (q->status == FS_FOUND)
|
||||
{
|
||||
FIL_ReadFile(q->filename, &ctx->buf);
|
||||
}
|
||||
|
||||
if (ctx->buf)
|
||||
{
|
||||
if (! ctx->silent)
|
||||
CONS_Printf(M_GetText("executing %s\n"), q->filename);
|
||||
|
||||
// insert text file into the command buffer
|
||||
COM_BufAddText((char *)ctx->buf);
|
||||
COM_BufAddText("\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (! ctx->noerror)
|
||||
CONS_Printf(M_GetText("couldn't execute file %s\n"), q->filename);
|
||||
}
|
||||
|
||||
Free_COM_Exec_Ctx(ctx);
|
||||
}
|
||||
|
||||
/** Executes a script file.
|
||||
*/
|
||||
static void COM_Exec_f(void)
|
||||
{
|
||||
UINT8 *buf = NULL;
|
||||
char filename[256];
|
||||
char filenamebuf[MAX_WADPATH];
|
||||
|
||||
struct COM_Exec_Ctx *ctx;
|
||||
|
||||
const char * filename;
|
||||
|
||||
filequery_t q;
|
||||
|
||||
if (COM_Argc() < 2 || COM_Argc() > 3)
|
||||
{
|
||||
@@ -765,37 +814,39 @@ static void COM_Exec_f(void)
|
||||
return;
|
||||
}
|
||||
|
||||
// load file
|
||||
// Try with Argv passed verbatim first, for back compat
|
||||
FIL_ReadFile(COM_Argv(1), &buf);
|
||||
filename = COM_Argv(1);
|
||||
|
||||
if (!buf)
|
||||
ctx = ZZ_Alloc(sizeof *ctx);
|
||||
|
||||
ctx->noerror = COM_CheckParm("-noerror");
|
||||
ctx->silent = COM_CheckParm("-silent");
|
||||
|
||||
if (COM_CheckParm("-sync"))
|
||||
{
|
||||
// Now try by searching the file path
|
||||
// filename is modified with the full found path
|
||||
strcpy(filename, COM_Argv(1));
|
||||
if (findfile(filename, NULL, true) != FS_NOTFOUND)
|
||||
FIL_ReadFile(filename, &buf);
|
||||
q.filename = filenamebuf;
|
||||
|
||||
if (!buf)
|
||||
strcpy(q.filename, filename);
|
||||
|
||||
if (FIL_FileOK(filename))
|
||||
{
|
||||
if (!COM_CheckParm("-noerror"))
|
||||
CONS_Printf(M_GetText("couldn't execute file %s\n"), COM_Argv(1));
|
||||
return;
|
||||
q.status = FS_FOUND;
|
||||
}
|
||||
else
|
||||
{
|
||||
q.status = findfile(q.filename, NULL, true);
|
||||
}
|
||||
|
||||
COM_ExecuteFile(&q, ctx);
|
||||
}
|
||||
else
|
||||
{
|
||||
q.filename = strcpy(ZZ_Alloc(MAX_WADPATH), filename);
|
||||
Append_async_addfile(ASYNC_EXEC, q.filename, ctx);
|
||||
}
|
||||
|
||||
if (!COM_CheckParm("-silent"))
|
||||
CONS_Printf(M_GetText("executing %s\n"), COM_Argv(1));
|
||||
|
||||
// insert text file into the command buffer
|
||||
COM_BufAddText((char *)buf);
|
||||
COM_BufAddText("\n");
|
||||
|
||||
// free buffer
|
||||
Z_Free(buf);
|
||||
}
|
||||
|
||||
|
||||
/** Delays execution of the rest of the commands until the next frame.
|
||||
* Allows sequences of commands like "jump; fire; backward".
|
||||
*/
|
||||
|
||||
@@ -59,6 +59,9 @@ void COM_ImmedExecute(const char *ptext);
|
||||
// Execute commands in buffer, flush them
|
||||
void COM_BufExecute(void);
|
||||
|
||||
// Execute a whole file (internal use only :v)
|
||||
void COM_ExecuteFile(void *query, void *ctx);
|
||||
|
||||
// As above; and progress the wait timer.
|
||||
void COM_BufTicker(void);
|
||||
|
||||
|
||||
@@ -1414,6 +1414,14 @@ void CONS_Printf(const char *fmt, ...)
|
||||
startup = con_startup;
|
||||
|
||||
Unlock_state();
|
||||
|
||||
|
||||
#ifdef HAVE_THREADS
|
||||
if (! I_on_main_thread())
|
||||
{
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
// if not in display loop, force screen update
|
||||
if (startup)
|
||||
|
||||
+259
@@ -0,0 +1,259 @@
|
||||
// SONIC ROBO BLAST 2 KART
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2020 by James R.
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
/// \file d_async.c
|
||||
/// \brief Add wad/exec config asynchronously to the main thread, but in order
|
||||
|
||||
#include "doomdef.h"
|
||||
#include "d_main.h"
|
||||
#include "d_async.h"
|
||||
#include "filesrch.h"
|
||||
#include "i_threads.h"
|
||||
#include "m_misc.h"
|
||||
#include "p_setup.h"
|
||||
#include "z_zone.h"
|
||||
|
||||
struct filename_queue;
|
||||
struct async_addfile;
|
||||
|
||||
typedef struct filename_queue filename_queue_t;
|
||||
typedef struct async_addfile async_addfile_t;
|
||||
|
||||
struct filename_queue
|
||||
{
|
||||
int type;
|
||||
char * name;
|
||||
void * u;/* exec command has some parameters that need know */
|
||||
filename_queue_t * next;
|
||||
};
|
||||
|
||||
struct async_addfile
|
||||
{
|
||||
int done;
|
||||
int query_size;
|
||||
int query_position;
|
||||
filequery_t * query;
|
||||
int * type;
|
||||
void ** u;
|
||||
async_addfile_t * next;
|
||||
};
|
||||
|
||||
static filename_queue_t * queue_head;
|
||||
static filename_queue_t * queue_tail;
|
||||
static int queue_size;
|
||||
|
||||
static I_mutex async_mutex;
|
||||
|
||||
static async_addfile_t * async_head;
|
||||
static async_addfile_t * async_tail;
|
||||
|
||||
static void
|
||||
Async_addfile_thread (async_addfile_t *file)
|
||||
{
|
||||
findmultiplefiles(file->query_size, file->query, false, true, &async_mutex);
|
||||
|
||||
I_lock_mutex(&async_mutex);
|
||||
{
|
||||
file->done = 1;
|
||||
}
|
||||
I_unlock_mutex(async_mutex);
|
||||
}
|
||||
|
||||
static void
|
||||
Do_addfile (int type, filequery_t *q, void *ctx)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case ASYNC_EXEC:
|
||||
COM_ExecuteFile(q, ctx);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Finish_async_addfile (void)
|
||||
{
|
||||
async_addfile_t * file = async_head;
|
||||
async_addfile_t * next;
|
||||
|
||||
filequery_t * q;
|
||||
|
||||
filestatus_t status;
|
||||
|
||||
int type;
|
||||
int done;
|
||||
|
||||
while (file != NULL)
|
||||
{
|
||||
while (file->query_position < file->query_size)
|
||||
{
|
||||
q = &file->query [file->query_position];
|
||||
type = file->type [file->query_position];
|
||||
|
||||
I_lock_mutex(&async_mutex);
|
||||
{
|
||||
status = q->status;
|
||||
}
|
||||
I_unlock_mutex(async_mutex);
|
||||
|
||||
if (status == FS_NOTCHECKED)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
Do_addfile(type, q, file->u[file->query_position]);
|
||||
}
|
||||
|
||||
Z_Free(q->filename);
|
||||
|
||||
file->query_position++;
|
||||
}
|
||||
|
||||
if (file->query_position < file->query_size)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
I_lock_mutex(&async_mutex);
|
||||
{
|
||||
done = file->done;
|
||||
}
|
||||
I_unlock_mutex(async_mutex);
|
||||
|
||||
if (done)
|
||||
{
|
||||
next = file->next;
|
||||
|
||||
Z_Free(file->u);
|
||||
Z_Free(file->type);
|
||||
Z_Free(file->query);
|
||||
Z_Free(file);
|
||||
|
||||
file = next;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
async_head = file;
|
||||
|
||||
if (file == NULL)
|
||||
{
|
||||
async_tail = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Append_async_addfile (int type, const char * filename, void * userdata)
|
||||
{
|
||||
char filenamebuf[MAX_WADPATH];
|
||||
|
||||
filename_queue_t * q;
|
||||
|
||||
filequery_t file;
|
||||
|
||||
if (FIL_FileOK(filename))
|
||||
{
|
||||
file.status = FS_FOUND;
|
||||
file.filename = filenamebuf;
|
||||
|
||||
strcpy(file.filename, filename);
|
||||
|
||||
Do_addfile(type, &file, userdata);
|
||||
}
|
||||
else
|
||||
{
|
||||
q = ZZ_Alloc(sizeof *q);
|
||||
|
||||
if (queue_tail != NULL)
|
||||
{
|
||||
queue_tail->next = q;
|
||||
}
|
||||
else
|
||||
{
|
||||
queue_head = q;
|
||||
}
|
||||
|
||||
queue_tail = q;
|
||||
queue_size++;
|
||||
|
||||
q->type = type;
|
||||
q->name = strcpy(ZZ_Alloc(MAX_WADPATH), filename);
|
||||
q->u = userdata;
|
||||
q->next = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Detach_async_addfile (void)
|
||||
{
|
||||
filename_queue_t * q = queue_head;
|
||||
filename_queue_t * next;
|
||||
|
||||
async_addfile_t * file;
|
||||
|
||||
filequery_t * query;
|
||||
int * type;
|
||||
void ** udata;
|
||||
|
||||
if (q != NULL)
|
||||
{
|
||||
file = ZZ_Alloc(sizeof *file);
|
||||
|
||||
if (async_tail != NULL)
|
||||
{
|
||||
async_tail->next = file;
|
||||
}
|
||||
else
|
||||
{
|
||||
async_head = file;
|
||||
}
|
||||
|
||||
async_tail = file;
|
||||
|
||||
file->done = 0;
|
||||
file->next = NULL;
|
||||
|
||||
file->query_size = queue_size;
|
||||
file->query_position = 0;
|
||||
|
||||
file->query = ZZ_Alloc(queue_size * sizeof (*file->query));
|
||||
file->type = ZZ_Alloc(queue_size * sizeof (*file->type));
|
||||
file->u = ZZ_Alloc(queue_size * sizeof (*file->u));
|
||||
|
||||
query = file->query;
|
||||
type = file->type;
|
||||
udata = file->u;
|
||||
|
||||
do
|
||||
{
|
||||
*type++ = q->type;
|
||||
*udata++ = q->u;
|
||||
|
||||
query->status = FS_NOTCHECKED;
|
||||
query->wantedmd5sum = NULL;
|
||||
query->filename = q->name;
|
||||
query++;
|
||||
|
||||
next = q->next;
|
||||
|
||||
Z_Free(q);
|
||||
}
|
||||
while (( q = next ) != NULL) ;
|
||||
|
||||
I_spawn_thread("async-addfile",
|
||||
(I_thread_fn)Async_addfile_thread, file);
|
||||
|
||||
queue_head = NULL;
|
||||
queue_tail = NULL;
|
||||
queue_size = 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
// SONIC ROBO BLAST 2 KART
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2020 by James R.
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
/// \file d_async.h
|
||||
/// \brief Add wad/exec config asynchronously to the main thread, but in order
|
||||
|
||||
#ifndef D_ASYNC_H
|
||||
#define D_ASYNC_H
|
||||
|
||||
enum
|
||||
{
|
||||
ASYNC_ADDFILE,
|
||||
ASYNC_EXEC,
|
||||
};
|
||||
|
||||
/*
|
||||
Queue a file to be added. Detach_async_addfile will spawn a thread that
|
||||
searches for any files if necessary.
|
||||
*/
|
||||
|
||||
void Append_async_addfile (int type, const char * filename, void * ctx);
|
||||
|
||||
/*
|
||||
Although the file searching is done on another thread, the actual adding of the
|
||||
wad or executing the config must be done on the main thread. This function is
|
||||
called every tic to check if a file was found so it can perform that last step.
|
||||
It does this in order.
|
||||
*/
|
||||
|
||||
void Finish_async_addfile (void);
|
||||
|
||||
/*
|
||||
Spawns a thread that searches for files that were queued.
|
||||
Called at the end of each tic.
|
||||
*/
|
||||
|
||||
void Detach_async_addfile (void);
|
||||
|
||||
#endif/*D_ASYNC_H*/
|
||||
@@ -45,6 +45,7 @@
|
||||
#include "lua_script.h"
|
||||
#include "lua_hook.h"
|
||||
#include "k_kart.h"
|
||||
#include "d_async.h"
|
||||
#include "s_sound.h" // sfx_syfail
|
||||
#include "m_perfstats.h"
|
||||
#include "d_main.h"
|
||||
@@ -6041,6 +6042,8 @@ boolean TryRunTics(tic_t realtics)
|
||||
|
||||
if (singletics)
|
||||
realtics = 1;
|
||||
|
||||
Finish_async_addfile();
|
||||
|
||||
if (realtics >= 1)
|
||||
{
|
||||
@@ -6118,6 +6121,8 @@ boolean TryRunTics(tic_t realtics)
|
||||
{
|
||||
hu_stopped = true;
|
||||
}
|
||||
|
||||
Detach_async_addfile();
|
||||
|
||||
return ticking;
|
||||
}
|
||||
|
||||
+10
-4
@@ -1164,13 +1164,13 @@ filestatus_t checkfilemd5(char *filename, const UINT8 *wantedmd5sum)
|
||||
// Rewritten by Monster Iestyn to be less stupid
|
||||
// Note: if completepath is true, "filename" is modified, but only if FS_FOUND is going to be returned
|
||||
// (Don't worry about WinCE's version of filesearch, nobody cares about that OS anymore)
|
||||
filestatus_t findfile(char *filename, const UINT8 *wantedmd5sum, boolean completepath)
|
||||
filestatus_t findmultiplefiles(int n, filequery_t *files, boolean checkmd5, boolean completepath, void *mutex_ptr)
|
||||
{
|
||||
filestatus_t homecheck; // store result of last file search
|
||||
boolean badmd5 = false; // store whether md5 was bad from either of the first two searches (if nothing was found in the third)
|
||||
|
||||
// first, check SRB2's "home" directory
|
||||
homecheck = filesearch(filename, srb2home, wantedmd5sum, completepath, 10);
|
||||
homecheck = filesearch(n, files, srb2home, checkmd5, completepath, 10, mutex_ptr);
|
||||
|
||||
if (homecheck == FS_FOUND) // we found the file, so return that we have :)
|
||||
return FS_FOUND;
|
||||
@@ -1179,7 +1179,7 @@ filestatus_t findfile(char *filename, const UINT8 *wantedmd5sum, boolean complet
|
||||
// if not found at all, just move on without doing anything
|
||||
|
||||
// next, check SRB2's "path" directory
|
||||
homecheck = filesearch(filename, srb2path, wantedmd5sum, completepath, 10);
|
||||
homecheck = filesearch(n, files, srb2path, checkmd5, completepath, 10, mutex_ptr);
|
||||
|
||||
if (homecheck == FS_FOUND) // we found the file, so return that we have :)
|
||||
return FS_FOUND;
|
||||
@@ -1188,7 +1188,7 @@ filestatus_t findfile(char *filename, const UINT8 *wantedmd5sum, boolean complet
|
||||
// if not found at all, just move on without doing anything
|
||||
|
||||
// finally check "." directory
|
||||
homecheck = filesearch(filename, ".", wantedmd5sum, completepath, 10);
|
||||
homecheck = filesearch(n, files, ".", checkmd5, completepath, 10, mutex_ptr);
|
||||
|
||||
if (homecheck != FS_NOTFOUND) // if not found this time, fall back on the below return statement
|
||||
return homecheck; // otherwise return the result we got
|
||||
@@ -1196,6 +1196,12 @@ filestatus_t findfile(char *filename, const UINT8 *wantedmd5sum, boolean complet
|
||||
return (badmd5 ? FS_MD5SUMBAD : FS_NOTFOUND); // md5 sum bad or file not found
|
||||
}
|
||||
|
||||
filestatus_t findfile(char *filename, const UINT8 *wantedmd5sum, boolean completepath)
|
||||
{
|
||||
filequery_t q = { FS_NOTFOUND, wantedmd5sum, filename };
|
||||
return findmultiplefiles(1, &q, ( wantedmd5sum != NULL ), completepath, NULL);
|
||||
}
|
||||
|
||||
#ifdef HAVE_CURL
|
||||
size_t curlwrite_data(void *ptr, size_t size, size_t nmemb, FILE *stream)
|
||||
{
|
||||
|
||||
+90
-22
@@ -29,6 +29,7 @@
|
||||
#include "m_misc.h"
|
||||
#include "z_zone.h"
|
||||
#include "m_menu.h" // Addons_option_Onchange
|
||||
#include "i_threads.h"
|
||||
|
||||
#if defined (_WIN32) && defined (_MSC_VER)
|
||||
|
||||
@@ -354,17 +355,44 @@ INT32 pathisdirectory(const char *path)
|
||||
return 0;
|
||||
}
|
||||
|
||||
filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *wantedmd5sum, boolean completepath, int maxsearchdepth)
|
||||
filestatus_t filesearch(int nfiles, filequery_t *files, const char *startpath, boolean checkmd5, boolean completepath, int maxsearchdepth, void *mutex_ptr)
|
||||
{
|
||||
filestatus_t retval = FS_NOTFOUND;
|
||||
const UINT8 *wantedmd5sum = NULL;
|
||||
DIR **dirhandle;
|
||||
struct dirent *dent;
|
||||
struct stat fsstat;
|
||||
int found = 0;
|
||||
char *searchname = strdup(filename);
|
||||
int depthleft = maxsearchdepth;
|
||||
char searchpath[1024];
|
||||
size_t *searchpathindex;
|
||||
int matched;
|
||||
int files_left = 0;
|
||||
int i;
|
||||
|
||||
#ifdef HAVE_THREADS
|
||||
#define Lock() I_lock_mutex ((I_mutex *)mutex_ptr)
|
||||
#define Unlock() I_unlock_mutex (((mutex_ptr) ? *(I_mutex *)mutex_ptr : NULL))
|
||||
#else
|
||||
#define Lock() ((void)0)
|
||||
#define Unlock() ((void)0)
|
||||
#endif
|
||||
|
||||
Lock();
|
||||
|
||||
for (i = 0; i < nfiles; ++i)
|
||||
{
|
||||
if (files[i].status != FS_FOUND)
|
||||
{
|
||||
files_left++;
|
||||
}
|
||||
}
|
||||
|
||||
Unlock();
|
||||
|
||||
if (! files_left)
|
||||
{
|
||||
return FS_FOUND;
|
||||
}
|
||||
|
||||
dirhandle = (DIR**) malloc(maxsearchdepth * sizeof (DIR*));
|
||||
searchpathindex = (size_t *) malloc(maxsearchdepth * sizeof (size_t));
|
||||
@@ -376,7 +404,6 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want
|
||||
|
||||
if (dirhandle[depthleft] == NULL)
|
||||
{
|
||||
free(searchname);
|
||||
free(dirhandle);
|
||||
free(searchpathindex);
|
||||
return FS_NOTFOUND;
|
||||
@@ -390,7 +417,7 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want
|
||||
else
|
||||
searchpathindex[depthleft]--;
|
||||
|
||||
while ((!found) && (depthleft < maxsearchdepth))
|
||||
while ((files_left) && (depthleft < maxsearchdepth))
|
||||
{
|
||||
searchpath[searchpathindex[depthleft]]=0;
|
||||
dent = readdir(dirhandle[depthleft]);
|
||||
@@ -448,34 +475,75 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want
|
||||
searchpath[searchpathindex[depthleft]-1]='/';
|
||||
searchpath[searchpathindex[depthleft]]=0;
|
||||
}
|
||||
else if (!strcasecmp(searchname, dent->d_name))
|
||||
else
|
||||
{
|
||||
switch (checkfilemd5(searchpath, wantedmd5sum))
|
||||
for (i = 0; i < nfiles; ++i)
|
||||
{
|
||||
case FS_FOUND:
|
||||
if (completepath)
|
||||
strcpy(filename,searchpath);
|
||||
else
|
||||
strcpy(filename,dent->d_name);
|
||||
retval = FS_FOUND;
|
||||
found = 1;
|
||||
break;
|
||||
case FS_MD5SUMBAD:
|
||||
retval = FS_MD5SUMBAD;
|
||||
break;
|
||||
default: // prevent some compiler warnings
|
||||
break;
|
||||
Lock();
|
||||
|
||||
if (checkmd5)
|
||||
{
|
||||
wantedmd5sum = files[i].wantedmd5sum;
|
||||
}
|
||||
|
||||
matched = (
|
||||
files[i].status != FS_FOUND &&
|
||||
!strcasecmp(files[i].filename, dent->d_name)
|
||||
);
|
||||
|
||||
Unlock();
|
||||
|
||||
if (matched)
|
||||
{
|
||||
switch (checkfilemd5(searchpath, wantedmd5sum))
|
||||
{
|
||||
case FS_FOUND:
|
||||
Lock();
|
||||
|
||||
if (completepath)
|
||||
strcpy(files[i].filename,searchpath);
|
||||
else
|
||||
strcpy(files[i].filename,dent->d_name);
|
||||
files[i].status = FS_FOUND;
|
||||
|
||||
Unlock();
|
||||
|
||||
files_left--;
|
||||
break;
|
||||
case FS_MD5SUMBAD:
|
||||
Lock();
|
||||
retval = files[i].status = FS_MD5SUMBAD;
|
||||
Unlock();
|
||||
break;
|
||||
default: // prevent some compiler warnings
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (; depthleft < maxsearchdepth; closedir(dirhandle[depthleft++]));
|
||||
|
||||
free(searchname);
|
||||
free(searchpathindex);
|
||||
free(dirhandle);
|
||||
|
||||
return retval;
|
||||
Lock();
|
||||
{
|
||||
for (i = 0; i < nfiles; ++i)
|
||||
{
|
||||
if (files[i].status != FS_FOUND && files[i].status != FS_MD5SUMBAD)
|
||||
{
|
||||
files[i].status = FS_NOTFOUND;
|
||||
}
|
||||
}
|
||||
}
|
||||
Unlock();
|
||||
|
||||
return ( (files_left) ? retval : FS_FOUND );
|
||||
|
||||
#undef Lock
|
||||
#undef Unlock
|
||||
}
|
||||
|
||||
char exttable[NUM_EXT_TABLE][7] = { // maximum extension length (currently 4) plus 3 (null terminator, stop, and length including previous two)
|
||||
|
||||
+18
-5
@@ -8,25 +8,38 @@
|
||||
#include "d_netfil.h"
|
||||
#include "m_menu.h" // MAXSTRINGLENGTH
|
||||
|
||||
typedef struct
|
||||
{
|
||||
filestatus_t status;
|
||||
const UINT8 * wantedmd5sum;
|
||||
char * filename;
|
||||
}
|
||||
filequery_t;
|
||||
|
||||
extern consvar_t cv_addons_option, cv_addons_folder, cv_addons_md5, cv_addons_showall, cv_addons_search_case, cv_addons_search_type;
|
||||
|
||||
/** \brief The filesearch function
|
||||
|
||||
This function search files, manly WADs and return back the status of the file
|
||||
|
||||
\param filename the file to look for
|
||||
\param nfiles number of files
|
||||
\param queries the files to look for
|
||||
\param startpath where to start look from
|
||||
\param wantedmd5sum want to check with MD5
|
||||
\param completepath want to return the complete path of the file?
|
||||
\param maxsearchdepth the max depth to search for the file
|
||||
|
||||
\return filestatus_t
|
||||
\return FS_FOUND if all files were found, FS_NOTFOUND or FS_MD5SUMBAD
|
||||
if some files were not found
|
||||
|
||||
|
||||
*/
|
||||
|
||||
filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *wantedmd5sum,
|
||||
boolean completepath, int maxsearchdepth);
|
||||
filestatus_t filesearch(int nfiles, filequery_t *queries, const char *startpath,
|
||||
boolean checkmd5, boolean completepath, int maxsearchdepth, void *mutex_ptr);
|
||||
|
||||
/* this is a better place for it tbh (im still too lazy to move the other) */
|
||||
filestatus_t findmultiplefiles(int nfiles, filequery_t *files,
|
||||
boolean checkmd5, boolean completepath, void *mutex_ptr);
|
||||
|
||||
#define menudepth 20
|
||||
|
||||
|
||||
@@ -27,6 +27,8 @@ void I_spawn_thread (const char *name, I_thread_fn, void *userdata);
|
||||
/* check in your thread whether to return early */
|
||||
int I_thread_is_stopped (void);
|
||||
|
||||
int I_on_main_thread (void);
|
||||
|
||||
void I_lock_mutex (I_mutex *);
|
||||
void I_unlock_mutex (I_mutex);
|
||||
|
||||
|
||||
+1
-1
@@ -504,7 +504,7 @@ void M_FirstLoadConfig(void)
|
||||
CV_InitFilterVar();
|
||||
|
||||
// load config, make sure those commands doesnt require the screen...
|
||||
COM_BufInsertText(va("exec \"%s\"\n", configfile));
|
||||
COM_BufInsertText(va("exec \"%s\" -sync\n", configfile));
|
||||
// no COM_BufExecute() needed; that does it right away
|
||||
|
||||
// don't filter anymore vars and don't let this convsvar be changed
|
||||
|
||||
+6
-2
@@ -3871,10 +3871,14 @@ static void pathonly(char *s)
|
||||
static const char *searchWad(const char *searchDir)
|
||||
{
|
||||
static char tempsw[256] = "";
|
||||
filequery_t fsquery;
|
||||
filestatus_t fstemp;
|
||||
|
||||
fsquery.filename = tempsw;
|
||||
|
||||
strcpy(tempsw, WADKEYWORD1);
|
||||
fstemp = filesearch(tempsw,searchDir,NULL,true,20);
|
||||
fsquery.status = FS_NOTFOUND;
|
||||
fstemp = filesearch(1,&fsquery,searchDir,false,true,20,NULL);
|
||||
if (fstemp == FS_FOUND)
|
||||
{
|
||||
pathonly(tempsw);
|
||||
@@ -3882,7 +3886,7 @@ static const char *searchWad(const char *searchDir)
|
||||
}
|
||||
|
||||
strcpy(tempsw, WADKEYWORD2);
|
||||
fstemp = filesearch(tempsw, searchDir, NULL, true, 20);
|
||||
fstemp = filesearch(1, &fsquery, searchDir, false, true, 20, NULL);
|
||||
if (fstemp == FS_FOUND)
|
||||
{
|
||||
pathonly(tempsw);
|
||||
|
||||
@@ -47,6 +47,8 @@ static I_mutex i_cond_pool_mutex;
|
||||
|
||||
static SDL_atomic_t i_threads_running = {1};
|
||||
|
||||
static SDL_threadID i_main_thread_id;
|
||||
|
||||
static Link
|
||||
Insert_link (
|
||||
Link * head,
|
||||
@@ -197,6 +199,12 @@ I_thread_is_stopped (void)
|
||||
return ( ! SDL_AtomicGet(&i_threads_running) );
|
||||
}
|
||||
|
||||
int
|
||||
I_on_main_thread (void)
|
||||
{
|
||||
return ( SDL_ThreadID() == i_main_thread_id );
|
||||
}
|
||||
|
||||
void
|
||||
I_start_threads (void)
|
||||
{
|
||||
@@ -211,6 +219,8 @@ I_start_threads (void)
|
||||
)){
|
||||
abort();
|
||||
}
|
||||
|
||||
i_main_thread_id = SDL_ThreadID();
|
||||
}
|
||||
|
||||
void
|
||||
@@ -283,6 +293,12 @@ I_lock_mutex (
|
||||
I_mutex * anchor
|
||||
){
|
||||
SDL_mutex * mutex;
|
||||
|
||||
if (! i_threads_running.value)
|
||||
return;
|
||||
|
||||
if (anchor == NULL)
|
||||
return;
|
||||
|
||||
mutex = Identity(
|
||||
&i_mutex_pool,
|
||||
@@ -299,6 +315,12 @@ void
|
||||
I_unlock_mutex (
|
||||
I_mutex id
|
||||
){
|
||||
if (! i_threads_running.value)
|
||||
return;
|
||||
|
||||
if (id == NULL)
|
||||
return;
|
||||
|
||||
if (SDL_UnlockMutex(id) == -1)
|
||||
abort();
|
||||
}
|
||||
@@ -309,6 +331,12 @@ I_hold_cond (
|
||||
I_mutex mutex_id
|
||||
){
|
||||
SDL_cond * cond;
|
||||
|
||||
if (! i_threads_running.value)
|
||||
return;
|
||||
|
||||
if (cond_anchor == NULL || mutex_id == NULL)
|
||||
return;
|
||||
|
||||
cond = Identity(
|
||||
&i_cond_pool,
|
||||
@@ -326,6 +354,12 @@ I_wake_one_cond (
|
||||
I_cond * anchor
|
||||
){
|
||||
SDL_cond * cond;
|
||||
|
||||
if (! i_threads_running.value)
|
||||
return;
|
||||
|
||||
if (anchor == NULL)
|
||||
return;
|
||||
|
||||
cond = Identity(
|
||||
&i_cond_pool,
|
||||
@@ -343,6 +377,12 @@ I_wake_all_cond (
|
||||
I_cond * anchor
|
||||
){
|
||||
SDL_cond * cond;
|
||||
|
||||
if (! i_threads_running.value)
|
||||
return;
|
||||
|
||||
if (anchor == NULL)
|
||||
return;
|
||||
|
||||
cond = Identity(
|
||||
&i_cond_pool,
|
||||
|
||||
+31
-2
@@ -904,17 +904,46 @@ void W_UnloadWadFile(UINT16 num)
|
||||
*/
|
||||
INT32 W_InitMultipleFiles(char **filenames, boolean addons)
|
||||
{
|
||||
char filenamebufs[MAX_WADFILES][MAX_WADPATH];
|
||||
filequery_t q[MAX_WADFILES];
|
||||
|
||||
int n = 0;
|
||||
int i;
|
||||
|
||||
INT32 rc = 1;
|
||||
INT32 overallrc = 1;
|
||||
|
||||
// will be realloced as lumps are added
|
||||
for (; *filenames; filenames++)
|
||||
{
|
||||
if (addons && !W_VerifyNMUSlumps(*filenames))
|
||||
if (FIL_FileOK(*filenames))
|
||||
{
|
||||
q[n].status = FS_FOUND;
|
||||
q[n].filename = *filenames;
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy(filenamebufs[n], *filenames);
|
||||
q[n].filename = filenamebufs[n];
|
||||
}
|
||||
n++;
|
||||
}
|
||||
|
||||
findmultiplefiles(n, q, false, true, NULL);
|
||||
|
||||
for (i = 0; i < n; ++i)
|
||||
{
|
||||
if (q[i].status != FS_FOUND)
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, M_GetText("File %s not found.\n"), q[i].filename);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (addons && !W_VerifyNMUSlumps(q[i].filename))
|
||||
G_SetGameModified(true, false);
|
||||
|
||||
//CONS_Debug(DBG_SETUP, "Loading %s\n", *filenames);
|
||||
rc = W_InitFile(*filenames, 0, 0, false);
|
||||
rc = W_InitFile(q[i].filename, 0, 0, false);
|
||||
if (rc == INT16_MAX)
|
||||
CONS_Printf(M_GetText("Errors occurred while loading %s; not added.\n"), *filenames);
|
||||
overallrc &= (rc != INT16_MAX) ? 1 : 0;
|
||||
|
||||
+37
-1
@@ -29,6 +29,7 @@
|
||||
#include "doomstat.h"
|
||||
#include "r_patch.h"
|
||||
#include "i_system.h" // I_GetFreeMem
|
||||
#include "i_threads.h"
|
||||
#include "i_video.h" // rendermode
|
||||
#include "z_zone.h"
|
||||
#include "m_misc.h" // M_Memcpy
|
||||
@@ -50,6 +51,16 @@ static boolean Z_calloc = false;
|
||||
//#define ZDEBUG2
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_THREADS
|
||||
static I_mutex z_mutex;
|
||||
|
||||
# define Lock_state() I_lock_mutex(&z_mutex)
|
||||
# define Unlock_state() I_unlock_mutex(z_mutex)
|
||||
#else/*HAVE_THREADS*/
|
||||
# define Lock_state()
|
||||
# define Unlock_state()
|
||||
#endif/*HAVE_THREADS*/
|
||||
|
||||
typedef struct memblock_s
|
||||
{
|
||||
void **user;
|
||||
@@ -135,6 +146,8 @@ void Z_Free(void *ptr)
|
||||
CONS_Debug(DBG_MEMORY, "Z_Free %s:%d\n", file, line);
|
||||
#endif
|
||||
|
||||
Lock_state();
|
||||
|
||||
block = MEMBLOCK(ptr);
|
||||
#ifdef PARANOIA
|
||||
if (block->id != ZONEID)
|
||||
@@ -167,6 +180,8 @@ void Z_Free(void *ptr)
|
||||
block->prev->next = block->next;
|
||||
block->next->prev = block->prev;
|
||||
free(block);
|
||||
|
||||
Unlock_state();
|
||||
}
|
||||
|
||||
/** malloc() that doesn't accept failure.
|
||||
@@ -233,6 +248,8 @@ void *Z_MallocAlign(size_t size, INT32 tag, void *user, INT32 alignbits)
|
||||
Z_calloc = false;
|
||||
#endif
|
||||
|
||||
Lock_state();
|
||||
|
||||
block->next = head.next;
|
||||
block->prev = &head;
|
||||
head.next = block;
|
||||
@@ -258,7 +275,10 @@ void *Z_MallocAlign(size_t size, INT32 tag, void *user, INT32 alignbits)
|
||||
block->user = user;
|
||||
*(void **)user = ptr;
|
||||
}
|
||||
else if (tag >= PU_PURGELEVEL)
|
||||
|
||||
Unlock_state();
|
||||
|
||||
if (tag >= PU_PURGELEVEL)
|
||||
I_Error("Z_Malloc: attempted to allocate purgable block "
|
||||
"(size %s) with no user", sizeu1(size));
|
||||
|
||||
@@ -392,6 +412,8 @@ void *Z_ReallocAlign(void *ptr, size_t size, INT32 tag, void *user, INT32 alignb
|
||||
void Z_FreeTags(INT32 lowtag, INT32 hightag)
|
||||
{
|
||||
memblock_t *block, *next;
|
||||
|
||||
Lock_state();
|
||||
|
||||
Z_CheckHeap(420);
|
||||
for (block = head.next; block != &head; block = next)
|
||||
@@ -400,6 +422,8 @@ void Z_FreeTags(INT32 lowtag, INT32 hightag)
|
||||
if (block->tag >= lowtag && block->tag <= hightag)
|
||||
Z_Free(MEMORY(block));
|
||||
}
|
||||
|
||||
Unlock_state();
|
||||
}
|
||||
|
||||
/** Iterates through all memory for a given set of tags.
|
||||
@@ -627,6 +651,8 @@ size_t Z_TagsUsage(INT32 lowtag, INT32 hightag)
|
||||
{
|
||||
size_t cnt = 0;
|
||||
memblock_t *rover;
|
||||
|
||||
Lock_state();
|
||||
|
||||
for (rover = head.next; rover != &head; rover = rover->next)
|
||||
{
|
||||
@@ -634,6 +660,8 @@ size_t Z_TagsUsage(INT32 lowtag, INT32 hightag)
|
||||
continue;
|
||||
cnt += rover->size + sizeof *rover;
|
||||
}
|
||||
|
||||
Unlock_state();
|
||||
|
||||
return cnt;
|
||||
}
|
||||
@@ -648,6 +676,8 @@ size_t Z_TagsUsage(INT32 lowtag, INT32 hightag)
|
||||
static void Command_Memfree_f(void)
|
||||
{
|
||||
size_t freebytes, totalbytes;
|
||||
|
||||
Lock_state();
|
||||
|
||||
Z_CheckHeap(-1);
|
||||
CONS_Printf("\x82%s", M_GetText("Memory Info\n"));
|
||||
@@ -677,6 +707,8 @@ static void Command_Memfree_f(void)
|
||||
freebytes = I_GetFreeMem(&totalbytes);
|
||||
CONS_Printf(M_GetText(" Total physical memory: %s KB\n"), sizeu1(totalbytes>>10));
|
||||
CONS_Printf(M_GetText("Available physical memory: %s KB\n"), sizeu1(freebytes>>10));
|
||||
|
||||
Unlock_state();
|
||||
}
|
||||
|
||||
|
||||
@@ -698,6 +730,8 @@ static void Command_Memdump_f(void)
|
||||
|
||||
if ((i = COM_CheckParm("-max")))
|
||||
maxtag = atoi(COM_Argv(i + 1));
|
||||
|
||||
Lock_state();
|
||||
|
||||
for (block = head.next; block != &head; block = block->next)
|
||||
if (block->tag >= mintag && block->tag <= maxtag)
|
||||
@@ -705,6 +739,8 @@ static void Command_Memdump_f(void)
|
||||
char *filename = strrchr(block->ownerfile, PATHSEP[0]);
|
||||
CONS_Printf("[%3d] %s (%s) bytes @ %s:%d\n", block->tag, sizeu1(block->size), sizeu2(block->realsize), filename ? filename + 1 : block->ownerfile, block->ownerline);
|
||||
}
|
||||
|
||||
Unlock_state();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
Reference in new issue
Block a user