mirror of
https://github.com/VCMP-SqMod/SqMod.git
synced 2025-06-16 07:07:13 +02:00
Rewrite logger to account for multiple-threads.
Implement error handling for worker VMs.
This commit is contained in:
@ -80,18 +80,6 @@ void Worker::Process(size_t jobs)
|
||||
}
|
||||
for (auto & t : workers)
|
||||
{
|
||||
const size_t logs = std::min(t->m_Logs.size_approx(), size_t{32});
|
||||
// Flush log messages
|
||||
for (size_t n = 0; n < logs; ++n)
|
||||
{
|
||||
std::unique_ptr< Log > log;
|
||||
// Try to get a log from the queue
|
||||
if (t->m_Logs.try_dequeue(log))
|
||||
{
|
||||
// Send it to the logger
|
||||
Logger::Get().Send(log->first, false, log->second.data(), log->second.size());
|
||||
}
|
||||
}
|
||||
for (size_t n = 0; n < jobs; ++n)
|
||||
{
|
||||
std::unique_ptr< BaseJob > job;
|
||||
@ -149,6 +137,12 @@ void Worker::Start()
|
||||
sq_setforeignptr(m_VM, this);
|
||||
// Tell the VM to use these functions to output user on error messages
|
||||
sq_setprintfunc(m_VM, PrintFunc, ErrorFunc);
|
||||
// Tell the VM to trigger this function on compile time errors
|
||||
sq_setcompilererrorhandler(m_VM, CompilerErrorHandler);
|
||||
// Push the runtime error handler on the stack and create a closure
|
||||
sq_newclosure(m_VM, RuntimeErrorHandler, 0);
|
||||
// Tell the VM to trigger this function on runtime errors
|
||||
sq_seterrorhandler(m_VM);
|
||||
// This is now running
|
||||
m_Running.test_and_set();
|
||||
}
|
||||
@ -188,18 +182,13 @@ void Worker::Work()
|
||||
}
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Worker::PrintFunc(HSQUIRRELVM vm, CSStr msg, ...)
|
||||
void Worker::PrintFunc(HSQUIRRELVM /*vm*/, CSStr msg, ...)
|
||||
{
|
||||
auto worker = reinterpret_cast< Worker * >(sq_getforeignptr(vm));
|
||||
// Initialize the variable argument list
|
||||
va_list args;
|
||||
va_start(args, msg);
|
||||
// Initialize an empty log message
|
||||
std::unique_ptr< Log > ptr(new Log{uint8_t{LOGL_USR}, String{}});
|
||||
// Attempt to generate the message
|
||||
PrintToStrFv(ptr->second, msg, args);
|
||||
// Let the main thread deal with it
|
||||
worker->m_Logs.enqueue(std::move(ptr));
|
||||
// Forward the message to the logger
|
||||
Logger::Get().SendFv(LOGL_USR, false, msg, args);
|
||||
// Finalize the variable argument list
|
||||
va_end(args);
|
||||
}
|
||||
@ -207,19 +196,43 @@ void Worker::PrintFunc(HSQUIRRELVM vm, CSStr msg, ...)
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Worker::ErrorFunc(HSQUIRRELVM vm, CSStr msg, ...)
|
||||
{
|
||||
auto worker = reinterpret_cast< Worker * >(sq_getforeignptr(vm));
|
||||
// Initialize the variable argument list
|
||||
va_list args;
|
||||
va_start(args, msg);
|
||||
// Initialize an empty log message
|
||||
std::unique_ptr< Log > ptr(new Log{uint8_t{LOGL_ERR}, String{}});
|
||||
// Attempt to generate the message
|
||||
PrintToStrFv(ptr->second, msg, args);
|
||||
// Let the main thread deal with it
|
||||
worker->m_Logs.enqueue(std::move(ptr));
|
||||
// Tell the logger to display debugging information
|
||||
Logger::Get().DebugFv(vm, msg, args);
|
||||
// Finalize the variable argument list
|
||||
va_end(args);
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
SQInteger Worker::RuntimeErrorHandler(HSQUIRRELVM vm)
|
||||
{
|
||||
// Was there a value thrown?
|
||||
if (sq_gettop(vm) < 1)
|
||||
{
|
||||
return SQ_OK; // No error to display!
|
||||
}
|
||||
// Attempt to generate the string value
|
||||
StackStrF val(vm, 2);
|
||||
// Have we failed to retrieve the string?
|
||||
if (SQ_FAILED(val.Proc(false)))
|
||||
{
|
||||
Logger::Get().DebugF(vm, _SC("Unknown runtime error has occurred"));
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger::Get().DebugF(vm, _SC("%s"), val.mPtr);
|
||||
}
|
||||
// We handled the error
|
||||
return SQ_OK;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Worker::CompilerErrorHandler(HSQUIRRELVM /*vm*/, CSStr desc, CSStr src, SQInteger line, SQInteger column)
|
||||
{
|
||||
LogFtl("Message: %s\n[\n=>Location: %s\n=>Line: %" PRINT_INT_FMT "\n=>Column: %" PRINT_INT_FMT "\n]", desc, src, line, column);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void TerminateWorkers()
|
||||
{
|
||||
|
@ -150,6 +150,7 @@ struct Worker
|
||||
m_PendingJobs.enqueue(job.Grab());
|
||||
}
|
||||
private:
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Worker thread container.
|
||||
*/
|
||||
@ -162,14 +163,6 @@ private:
|
||||
*
|
||||
*/
|
||||
using Jobs = ConcurrentQueue< std::unique_ptr< BaseJob > >;
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
*
|
||||
*/
|
||||
using Log = std::pair< uint8_t, String >;
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
*
|
||||
*/
|
||||
using Logs = ConcurrentQueue< std::unique_ptr< Log > >;
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Pending job queue.
|
||||
*/
|
||||
@ -178,10 +171,6 @@ private:
|
||||
* Finished job queue.
|
||||
*/
|
||||
Jobs m_FinishedJobs;
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Log message queue.
|
||||
*/
|
||||
Logs m_Logs;
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Loop state.
|
||||
*/
|
||||
@ -215,6 +204,14 @@ private:
|
||||
*/
|
||||
static void PrintFunc(HSQUIRRELVM vm, CSStr msg, ...);
|
||||
static void ErrorFunc(HSQUIRRELVM vm, CSStr msg, ...);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Script error handlers.
|
||||
*/
|
||||
static SQInteger RuntimeErrorHandler(HSQUIRRELVM vm);
|
||||
static void CompilerErrorHandler(HSQUIRRELVM vm, CSStr desc, CSStr src,
|
||||
SQInteger line, SQInteger column);
|
||||
|
||||
};
|
||||
|
||||
} // Namespace:: SqMod
|
||||
|
@ -108,11 +108,26 @@ struct EvaluateJob : public BaseJob
|
||||
*/
|
||||
bool Start(HSQUIRRELVM vm, Worker & worker) override
|
||||
{
|
||||
sq_compilebuffer(vm, mCode.data(), mCode.size(), mName.data(), SQTrue);
|
||||
SQRESULT r = sq_compilebuffer(vm, mCode.data(), mCode.size(), mName.data(), SQTrue);
|
||||
// See if the code could be compiled
|
||||
if (SQ_FAILED(r))
|
||||
{
|
||||
return false; // Job failed
|
||||
}
|
||||
// Backup the stack top
|
||||
SQInteger top = sq_gettop(vm);
|
||||
// Push the root table as environment
|
||||
sq_pushroottable(vm);
|
||||
sq_call(vm, 1, false, true);
|
||||
// Attempt to invoke the compiled code
|
||||
r = sq_call(vm, 1, SQFalse, SQTrue);
|
||||
// Restore the stack top
|
||||
sq_settop(vm, top);
|
||||
// See if the code could be evaluated
|
||||
if (SQ_FAILED(r))
|
||||
{
|
||||
return false; // Job failed
|
||||
}
|
||||
// Job completed
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
Reference in New Issue
Block a user