Skip to content

Commit

Permalink
Use the standard thread library for the lua interpreter
Browse files Browse the repository at this point in the history
  • Loading branch information
TheGondos committed Jul 2, 2023
1 parent 32ec9b4 commit dac4627
Show file tree
Hide file tree
Showing 8 changed files with 75 additions and 97 deletions.
29 changes: 9 additions & 20 deletions Src/Module/LuaScript/LuaInline/LuaInline.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@
#define ORBITER_MODULE
#include "orbitersdk.h"
#include "LuaInline.h"
#include <direct.h>
#include <process.h>

// ==============================================================
// class InterpreterList::Environment: implementation
Expand All @@ -34,23 +32,17 @@ InterpreterList::Environment::Environment()
{
cmd = NULL;
singleCmd = false;
hThread = NULL;
interp = CreateInterpreter ();
}

InterpreterList::Environment::~Environment()
{
if (interp) {
if (hThread) {
if (hThread.joinable()) {
termInterp = true;
interp->Terminate();
interp->EndExec(); // give the thread opportunity to close

if (WaitForSingleObject (hThread, 1000) != 0) {
oapiWriteLog("LuaInline: timeout while waiting for interpreter thread");
TerminateThread (hThread, 0);
}
CloseHandle (hThread);
interp->StepInterpreter(); // give the thread opportunity to close
hThread.join();
}
delete interp;
}
Expand All @@ -62,7 +54,7 @@ Interpreter *InterpreterList::Environment::CreateInterpreter ()
termInterp = false;
interp = new Interpreter ();
interp->Initialise();
hThread = (HANDLE)_beginthreadex (NULL, 4096, &InterpreterThreadProc, this, 0, &id);
hThread = std::thread(InterpreterThreadProc, this);
return interp;
}

Expand All @@ -73,7 +65,7 @@ unsigned int WINAPI InterpreterList::Environment::InterpreterThreadProc (LPVOID

// interpreter loop
for (;;) {
interp->WaitExec(); // wait for execution permission
interp->WaitForStep(); // wait for execution permission
if (env->termInterp) break; // close thread requested
if (env->cmd) {
interp->RunChunk (env->cmd, strlen (env->cmd)); // run command from buffer
Expand All @@ -84,10 +76,9 @@ unsigned int WINAPI InterpreterList::Environment::InterpreterThreadProc (LPVOID
interp->RunChunk ("", 0); // idle loop
}
if (interp->Status() == 1) break;
interp->EndExec(); // return control
interp->StepDone(); // return control
}
interp->EndExec(); // return mutex (is this necessary?)
_endthreadex(0);
interp->StepDone(); // return mutex (is this necessary?)
return 0;
}

Expand Down Expand Up @@ -118,8 +109,7 @@ void InterpreterList::clbkPostStep (double simt, double simdt, double mjd)

for (i = 0; i < nlist; i++) { // let the interpreter do some work
if (list[i]->interp->IsBusy() || list[i]->cmd || list[i]->interp->nJobs()) {
list[i]->interp->EndExec();
list[i]->interp->WaitExec();
list[i]->interp->StepInterpreter();
}
}
}
Expand Down Expand Up @@ -237,8 +227,7 @@ DLLCLBK bool opcExecScriptCmd (INTERPRETERHANDLE hInterp, const char *cmd)
env->cmd = str;
while (env->cmd) {
// wait until command has been executed
env->interp->EndExec();
env->interp->WaitExec();
env->interp->StepInterpreter();
}
if (cmd_async) // restore the asynchronous request
env->cmd = cmd_async;
Expand Down
5 changes: 3 additions & 2 deletions Src/Module/LuaScript/LuaInline/LuaInline.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#define __LUAINLINE_H

#include "Interpreter.h"
#include <thread>

// ==============================================================
// class InterpreterList: interface
Expand All @@ -35,11 +36,11 @@ class InterpreterList: public oapi::Module {
~Environment();
Interpreter *CreateInterpreter ();
Interpreter *interp; // interpreter instance
HANDLE hThread; // interpreter thread
std::thread hThread; // interpreter thread
bool termInterp; // interpreter kill flag
bool singleCmd; // terminate after single command
char *cmd; // interpreter command
static unsigned int WINAPI InterpreterThreadProc (LPVOID context);
static unsigned int InterpreterThreadProc (void *context);
};

InterpreterList (HINSTANCE hDLL);
Expand Down
44 changes: 19 additions & 25 deletions Src/Module/LuaScript/LuaInterpreter/Interpreter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,17 +57,11 @@ Interpreter::Interpreter ()
// store interpreter context in the registry
lua_pushlightuserdata (L, this);
lua_setfield (L, LUA_REGISTRYINDEX, "interp");

hExecMutex = CreateMutex (NULL, TRUE, NULL);
hWaitMutex = CreateMutex (NULL, FALSE, NULL);
}

Interpreter::~Interpreter ()
{
lua_close (L);

if (hExecMutex) CloseHandle (hExecMutex);
if (hWaitMutex) CloseHandle (hWaitMutex);
}

void Interpreter::Initialise ()
Expand Down Expand Up @@ -551,19 +545,26 @@ void Interpreter::lua_pushsketchpad (lua_State *L, oapi::Sketchpad *skp)
#endif
}

void Interpreter::WaitExec (DWORD timeout)
void Interpreter::StepInterpreter ()
{
// Called by orbiter thread or interpreter thread to wait its turn
// Orbiter waits for the script for 1 second to return
WaitForSingleObject (hWaitMutex, timeout); // wait for synchronisation mutex
WaitForSingleObject (hExecMutex, timeout); // wait for execution mutex
ReleaseMutex (hWaitMutex); // release synchronisation mutex
// notify the interpreter
m_InterpRun = true;
m_InterpCV.notify_one();

// wait for it
std::unique_lock<std::mutex> lk(m_InterpMtx);
m_InterpCV.wait(lk, [&] {return !m_InterpRun.load(); });
}

void Interpreter::EndExec ()
void Interpreter::WaitForStep ()
{
std::unique_lock<std::mutex> lk(m_InterpMtx);
m_InterpCV.wait(lk, [&] {return m_InterpRun.load(); });
}
void Interpreter::StepDone()
{
// called by orbiter thread or interpreter thread to hand over control
ReleaseMutex (hExecMutex);
m_InterpRun = false;
m_InterpCV.notify_one();
}

void Interpreter::frameskip (lua_State *L)
Expand All @@ -572,19 +573,12 @@ void Interpreter::frameskip (lua_State *L)
lua_pushboolean(L, 1);
lua_setfield (L, LUA_GLOBALSINDEX, "wait_exit");
} else {
EndExec();
WaitExec();
StepDone();
// yield to the orbiter thread
WaitForStep();
}
}

int Interpreter::ProcessChunk (const char *chunk, int n)
{
WaitExec();
int res = RunChunk (chunk, n);
EndExec();
return res;
}

int Interpreter::RunChunk (const char *chunk, int n)
{
int res = 0;
Expand Down
31 changes: 18 additions & 13 deletions Src/Module/LuaScript/LuaInterpreter/Interpreter.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ extern "C" {

#include "OrbiterAPI.h"
#include "VesselAPI.h" // for TOUCHDOWNVTX
#include <mutex>

#define PRMTP_NIL 0x01
#define PRMTP_NUMBER 0x02
Expand Down Expand Up @@ -118,22 +119,27 @@ class INTERPRETERLIB Interpreter {

void PostStep (double simt, double simdt, double mjd);

/**
* \brief Handover execution to the interpreter thread.
* \note This is called by the orbiter thread to signal the interpreter
* thread to run. The orbiter thread blocks until the interpreter has
* done its work.
*/
void StepInterpreter();

/**
* \brief Wait for thread execution.
* \note This is called by either the orbiter thread or the interpreter
* thread when they are waiting to regain execution control.
* \note This is called by the interpreter thread when it's
* waiting to regain execution control.
*/
virtual void WaitExec (DWORD timeout = INFINITE);
void WaitForStep ();

/**
* \brief Release thread execution.
* \param timeout time [ms] to wait for the mutex. Default is infinite
* (wait does not time out).
* \note This is called by either the orbiter thread or the interpreter
* thread after finishing a cycle to hand control over to the other
* thread.
* \note This is called by the interpreter thread after
* finishing a cycle to hand control over to the orbiter thread.
*/
virtual void EndExec ();
void StepDone ();

/**
* \brief Define functions for interfacing with Orbiter API
Expand All @@ -153,8 +159,6 @@ class INTERPRETERLIB Interpreter {
*/
virtual void LoadStartupScript ();

virtual int ProcessChunk (const char *chunk, int n);

/**
* \brief Executes a command or script.
* \param chunk command line string
Expand Down Expand Up @@ -812,8 +816,9 @@ class INTERPRETERLIB Interpreter {
friend int OpenHelp (void *context);

private:
HANDLE hExecMutex; // flow control synchronisation
HANDLE hWaitMutex;
std::mutex m_InterpMtx;
std::condition_variable m_InterpCV;
std::atomic<bool> m_InterpRun;

bool bExecLocal; // flag for locally created mutexes
bool bWaitLocal;
Expand Down
31 changes: 10 additions & 21 deletions Src/Plugin/LuaConsole/LuaConsole.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
#include "LuaConsole.h"
#include "ConsoleCfg.h"
#include "resource.h"
#include <process.h>
#include <set>

using namespace oapi;
Expand All @@ -25,7 +24,6 @@ char cConsoleCmd[1024] = "\0";
LuaConsole::LuaConsole (HINSTANCE hDLL): Module (hDLL)
{
hWnd = NULL;
hThread = NULL;
interp = NULL;
bRefresh = false;
fW = 0;
Expand Down Expand Up @@ -113,16 +111,11 @@ void LuaConsole::clbkSimulationEnd ()
{
// Kill the interpreter thread
if (interp) {
if (hThread) {
termInterp = true;
termInterp = true;
if (hThread.joinable()) {
interp->Terminate();
interp->EndExec(); // give the thread opportunity to close
if (WaitForSingleObject (hThread, 1000) != 0) {
oapiWriteLog ("LuaConsole: timeout while waiting for interpreter thread");
TerminateThread (hThread, 0);
}
CloseHandle (hThread);
hThread = NULL;
interp->StepInterpreter(); // give the thread opportunity to close
hThread.join();
}
delete interp;
interp = NULL;
Expand All @@ -138,9 +131,7 @@ void LuaConsole::clbkPreStep (double simt, double simdt, double mjd)
{
if (interp) {
if (interp->IsBusy() || cConsoleCmd[0] || interp->nJobs()) { // let the interpreter do some work
interp->EndExec(); // orbiter hands over control
// At this point the interpreter is performing one cycle
interp->WaitExec(); // orbiter waits to get back control
interp->StepInterpreter();
}
if (bRefresh) {
UpdateScrollbar();
Expand Down Expand Up @@ -628,31 +619,29 @@ DLLCLBK void ExitModule (HINSTANCE hDLL)

Interpreter *LuaConsole::CreateInterpreter ()
{
unsigned int id;
termInterp = false;
interp = new ConsoleInterpreter (this);
interp->Initialise();
hThread = (HANDLE)_beginthreadex (NULL, 4096, &InterpreterThreadProc, this, 0, &id);
hThread = std::thread(InterpreterThreadProc, this);
return interp;
}
// Interpreter thread function
unsigned int WINAPI LuaConsole::InterpreterThreadProc (LPVOID context)
unsigned int LuaConsole::InterpreterThreadProc (void *context)
{
int res;
LuaConsole *console = (LuaConsole*)context;
ConsoleInterpreter *interp = (ConsoleInterpreter*)console->interp;

// interpreter loop
for (;;) {
interp->WaitExec(); // wait for execution permission
interp->WaitForStep(); // wait for execution permission
if (console->termInterp) break; // close thread requested
res = interp->RunChunk (cConsoleCmd, strlen (cConsoleCmd)); // run command from buffer
if (interp->Status() == 1) break; // close thread requested
cConsoleCmd[0] = '\0'; // free buffer
console->bRefresh = (res != -1); // signal terminal refresh
interp->EndExec(); // return control
interp->StepDone(); // return control
}
interp->EndExec(); // release mutex (is this necessary?)
_endthreadex(0);
interp->StepDone(); // wake the main thread when we die
return 0;
}
5 changes: 3 additions & 2 deletions Src/Plugin/LuaConsole/LuaConsole.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "OrbiterAPI.h"
#include "ModuleAPI.h"
#include "ConsoleInterpreter.h"
#include <thread>

#define NLINE 100 // number of buffered lines

Expand Down Expand Up @@ -42,14 +43,14 @@ class LuaConsole: public oapi::Module {
private:
static INT_PTR CALLBACK DlgProc (HWND, UINT, WPARAM, LPARAM);
static LRESULT WINAPI TermProcHook (HWND, UINT, WPARAM, LPARAM);
static unsigned int WINAPI InterpreterThreadProc (LPVOID context);
static unsigned int InterpreterThreadProc (void *context);
static void OpenDlgClbk (void *context); // called when user requests console window
Interpreter *CreateInterpreter ();
void AddLine (const char *str, int mode=1); // add line to buffer
void Clear ();
void InputLine (const char *str); // user input
bool ScanHistory (int step); // recall previous command to input buffer
HANDLE hThread; // interpreter thread handle
std::thread hThread; // interpreter thread handle
bool termInterp;

Interpreter *interp; // interpreter instance
Expand Down
Loading

0 comments on commit dac4627

Please sign in to comment.