diff options
Diffstat (limited to 'src/wren_inter')
| -rw-r--r-- | src/wren_inter/wren_inter.c | 98 | ||||
| -rw-r--r-- | src/wren_inter/wren_inter.h | 14 |
2 files changed, 111 insertions, 1 deletions
diff --git a/src/wren_inter/wren_inter.c b/src/wren_inter/wren_inter.c index 10ecc93..868b2fe 100644 --- a/src/wren_inter/wren_inter.c +++ b/src/wren_inter/wren_inter.c @@ -33,6 +33,7 @@ void errorFn(WrenVM* vm, WrenErrorType errorType, } } +// Obsolete char *EvaluateScript(char *script) { TraceLog(LOG_INFO, "Evaluating %s...", script); WrenVM *vm = InterpreterPrepareMachine(); @@ -77,3 +78,100 @@ void InterpreterFreeMachine(WrenVM *vm) { if (sb != NULL && sb->val != NULL) free(sb); wrenFreeVM(vm); } + +// ========== Async ========== + +typedef struct { + // The data that you want to access in the worker + void *data; + // Toggle this to true when the task is finished + bool is_done; +} Task; + +bool RunWithCancellation(Task *task, void *(*runner) (void *), int timeout); + +#if defined(unix) || defined(__unix__) || defined(__unix) + +#include <threads.h> +#include <pthread.h> +#include <unistd.h> + +// Returns false if the process was aborted +bool RunWithCancellation(Task *task, void *(*runner) (void *), int timeout) { + pthread_t thread_id; + if (pthread_create(&thread_id, NULL, runner, &task) != 0) { + TraceLog(LOG_ERROR, "Failed to create a pthread"); + return RESULT_INIT_ERROR; + } + + int elapsed = 0; + while (!task->is_done && elapsed < timeout) { + sleep(1); + elapsed += 1; + } + + if (!task->is_done) { + pthread_cancel(thread_id); + pthread_join(thread_id, NULL); + return false; + } + + return true; +} + +#endif + +// The task that the interpreter would need to run. Made for async reasons +typedef struct { + WrenVM *vm; + const char *module; + const char *script; + WrenInterpretResult result; + bool is_done; +} wrenTask; + +// Runs the wrenTask asynchronously +// FIX: Inject the cancellation parameters inside the worker thread definition +void *wren_worker(void *arg) { + int old_type; + pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &old_type); // + + Task *task_raw = (Task*)arg; + wrenTask *task = (wrenTask*)task_raw->data; + task->result = wrenInterpret(task->vm, task->module, task->script); + task_raw->is_done = true; + return NULL; +} + + +enum PUZZLE_TEST_RESULT wrenInterpretLimited(WrenVM* vm, const char* module, + const char* script, int sMax) { + + wrenTask *data = malloc(sizeof(wrenTask)); + data->vm = vm; + data->module = module; + data->script = script; + data->result = 0; + + Task *task = malloc(sizeof(Task)); + task->is_done = false; + task->data = data; + + if (!RunWithCancellation(task, wren_worker, sMax)) { + return RESULT_TIMEOUT; + } + + WrenInterpretResult interpret_res = data->result; + + free(data); + free(task); + + switch (interpret_res) { + case WREN_RESULT_COMPILE_ERROR: + return RESULT_COMPTIME_ERR; + case WREN_RESULT_RUNTIME_ERROR: + return RESULT_RUNTIME_ERR; + default: break; + } + return RESULT_OK; +} diff --git a/src/wren_inter/wren_inter.h b/src/wren_inter/wren_inter.h index 100f946..a84323f 100644 --- a/src/wren_inter/wren_inter.h +++ b/src/wren_inter/wren_inter.h @@ -3,10 +3,22 @@ #include <wren.h> -char *EvaluateScript(char *script); +enum PUZZLE_TEST_RESULT { + RESULT_OK = 0, + RESULT_WRONG_ANSWER, + RESULT_COMPTIME_NO_ENTRY, + RESULT_COMPTIME_ERR, + RESULT_RUNTIME_ERR, + // TODO: add async evaluation to prevent `while (true)` situation + RESULT_TIMEOUT, + RESULT_INIT_ERROR, +}; WrenVM *InterpreterPrepareMachine(); char *GetMachineOutput(WrenVM *vm); void InterpreterFreeMachine(WrenVM *vm); +// Runs the machine and returns +enum PUZZLE_TEST_RESULT wrenInterpretLimited(WrenVM *vm, const char *module, + const char *script, int sMax); #endif // WREN_INTER_H |
