summaryrefslogtreecommitdiff
path: root/src/wren_inter
diff options
context:
space:
mode:
Diffstat (limited to 'src/wren_inter')
-rw-r--r--src/wren_inter/wren_inter.c98
-rw-r--r--src/wren_inter/wren_inter.h14
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