Add module for Scheduler.
Also reorganizes some code to make it easier to add more modules.
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "uv.h"
|
||||
|
||||
#include "scheduler.h"
|
||||
#include "wren.h"
|
||||
#include "vm.h"
|
||||
|
||||
// This method resumes a fiber that is suspended waiting on an asynchronous
|
||||
// operation. The first resumes it with zero arguments, and the second passes
|
||||
// one.
|
||||
static WrenValue* resume;
|
||||
static WrenValue* resumeWithArg;
|
||||
|
||||
static void captureMethods(WrenVM* vm)
|
||||
{
|
||||
resume = wrenGetMethod(vm, "scheduler", "Scheduler", "resume_(_)");
|
||||
resumeWithArg = wrenGetMethod(vm, "scheduler", "Scheduler", "resume_(_,_)");
|
||||
}
|
||||
|
||||
WrenForeignMethodFn schedulerBindForeign(
|
||||
WrenVM* vm, const char* className, bool isStatic, const char* signature)
|
||||
{
|
||||
if (strcmp(className, "Scheduler") != 0) return NULL;
|
||||
|
||||
if (isStatic && strcmp(signature, "captureMethods_()") == 0) return captureMethods;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void schedulerResume(WrenValue* fiber)
|
||||
{
|
||||
wrenCall(getVM(), resume, NULL, "v", fiber);
|
||||
wrenReleaseValue(getVM(), fiber);
|
||||
}
|
||||
|
||||
void schedulerReleaseMethods()
|
||||
{
|
||||
if (resume != NULL) wrenReleaseValue(getVM(), resume);
|
||||
if (resumeWithArg != NULL) wrenReleaseValue(getVM(), resumeWithArg);
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
#ifndef scheduler_h
|
||||
#define scheduler_h
|
||||
|
||||
#include "wren.h"
|
||||
|
||||
WrenForeignMethodFn schedulerBindForeign(
|
||||
WrenVM* vm, const char* className, bool isStatic, const char* signature);
|
||||
|
||||
void schedulerResume(WrenValue* fiber);
|
||||
|
||||
void schedulerReleaseMethods();
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,26 @@
|
||||
class Scheduler {
|
||||
static add(callable) {
|
||||
if (__scheduled == null) __scheduled = []
|
||||
|
||||
__scheduled.add(Fiber.new {
|
||||
callable.call()
|
||||
runNextScheduled_()
|
||||
})
|
||||
}
|
||||
|
||||
// Called by native code.
|
||||
static resume_(fiber) { fiber.transfer() }
|
||||
static resume_(fiber, arg) { fiber.transfer(arg) }
|
||||
|
||||
static runNextScheduled_() {
|
||||
if (__scheduled == null || __scheduled.isEmpty) {
|
||||
return Fiber.suspend()
|
||||
} else {
|
||||
return __scheduled.removeAt(0).transfer()
|
||||
}
|
||||
}
|
||||
|
||||
foreign static captureMethods_()
|
||||
}
|
||||
|
||||
Scheduler.captureMethods_()
|
||||
@@ -0,0 +1,28 @@
|
||||
// Generated automatically from src/module/scheduler.wren. Do not edit.
|
||||
static const char* schedulerModuleSource =
|
||||
"class Scheduler {\n"
|
||||
" static add(callable) {\n"
|
||||
" if (__scheduled == null) __scheduled = []\n"
|
||||
"\n"
|
||||
" __scheduled.add(Fiber.new {\n"
|
||||
" callable.call()\n"
|
||||
" runNextScheduled_()\n"
|
||||
" })\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" // Called by native code.\n"
|
||||
" static resume_(fiber) { fiber.transfer() }\n"
|
||||
" static resume_(fiber, arg) { fiber.transfer(arg) }\n"
|
||||
"\n"
|
||||
" static runNextScheduled_() {\n"
|
||||
" if (__scheduled == null || __scheduled.isEmpty) {\n"
|
||||
" return Fiber.suspend()\n"
|
||||
" } else {\n"
|
||||
" return __scheduled.removeAt(0).transfer()\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" foreign static captureMethods_()\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"Scheduler.captureMethods_()\n";
|
||||
+3
-28
@@ -3,14 +3,10 @@
|
||||
|
||||
#include "uv.h"
|
||||
|
||||
#include "scheduler.h"
|
||||
#include "timer.h"
|
||||
#include "wren.h"
|
||||
#include "vm.h"
|
||||
|
||||
#include "timer.wren.inc"
|
||||
|
||||
// The Wren method to call when a timer has completed.
|
||||
static WrenValue* resumeTimer;
|
||||
#include "wren.h"
|
||||
|
||||
// Called by libuv when the timer finished closing.
|
||||
static void timerCloseCallback(uv_handle_t* handle)
|
||||
@@ -27,18 +23,11 @@ static void timerCallback(uv_timer_t* handle)
|
||||
uv_close((uv_handle_t*)handle, timerCloseCallback);
|
||||
|
||||
// Run the fiber that was sleeping.
|
||||
wrenCall(getVM(), resumeTimer, NULL, "v", fiber);
|
||||
wrenReleaseValue(getVM(), fiber);
|
||||
schedulerResume(fiber);
|
||||
}
|
||||
|
||||
static void startTimer(WrenVM* vm)
|
||||
{
|
||||
// If we haven't looked up the resume method yet, grab it now.
|
||||
if (resumeTimer == NULL)
|
||||
{
|
||||
resumeTimer = wrenGetMethod(vm, "timer", "Timer", "resumeTimer_(_)");
|
||||
}
|
||||
|
||||
int milliseconds = (int)wrenGetArgumentDouble(vm, 1);
|
||||
WrenValue* fiber = wrenGetArgumentValue(vm, 2);
|
||||
|
||||
@@ -50,15 +39,6 @@ static void startTimer(WrenVM* vm)
|
||||
uv_timer_start(handle, timerCallback, milliseconds, 0);
|
||||
}
|
||||
|
||||
char* timerGetSource()
|
||||
{
|
||||
size_t length = strlen(timerModuleSource);
|
||||
char* copy = (char*)malloc(length + 1);
|
||||
strncpy(copy, timerModuleSource, length + 1);
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
WrenForeignMethodFn timerBindForeign(
|
||||
WrenVM* vm, const char* className, bool isStatic, const char* signature)
|
||||
{
|
||||
@@ -68,8 +48,3 @@ WrenForeignMethodFn timerBindForeign(
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void timerReleaseMethods()
|
||||
{
|
||||
if (resumeTimer != NULL) wrenReleaseValue(getVM(), resumeTimer);
|
||||
}
|
||||
|
||||
@@ -3,11 +3,7 @@
|
||||
|
||||
#include "wren.h"
|
||||
|
||||
char* timerGetSource();
|
||||
|
||||
WrenForeignMethodFn timerBindForeign(
|
||||
WrenVM* vm, const char* className, bool isStatic, const char* signature);
|
||||
|
||||
void timerReleaseMethods();
|
||||
|
||||
#endif
|
||||
|
||||
+4
-25
@@ -1,34 +1,13 @@
|
||||
import "scheduler" for Scheduler
|
||||
|
||||
class Timer {
|
||||
static sleep(milliseconds) {
|
||||
if (!(milliseconds is Num)) Fiber.abort("Milliseconds must be a number.")
|
||||
if (milliseconds < 0) Fiber.abort("Milliseconds cannot be negative.")
|
||||
|
||||
startTimer_(milliseconds, Fiber.current)
|
||||
|
||||
runNextScheduled_()
|
||||
}
|
||||
|
||||
// TODO: Once the CLI modules are more fleshed out, find a better place to
|
||||
// put this.
|
||||
static schedule(callable) {
|
||||
if (__scheduled == null) __scheduled = []
|
||||
__scheduled.add(Fiber.new {
|
||||
callable.call()
|
||||
runNextScheduled_()
|
||||
})
|
||||
Scheduler.runNextScheduled_()
|
||||
}
|
||||
|
||||
foreign static startTimer_(milliseconds, fiber)
|
||||
|
||||
// Called by native code.
|
||||
static resumeTimer_(fiber) {
|
||||
fiber.transfer()
|
||||
}
|
||||
|
||||
static runNextScheduled_() {
|
||||
if (__scheduled == null || __scheduled.isEmpty) {
|
||||
Fiber.suspend()
|
||||
} else {
|
||||
__scheduled.removeAt(0).transfer()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,36 +1,15 @@
|
||||
// Generated automatically from src/module/timer.wren. Do not edit.
|
||||
static const char* timerModuleSource =
|
||||
"import \"scheduler\" for Scheduler\n"
|
||||
"\n"
|
||||
"class Timer {\n"
|
||||
" static sleep(milliseconds) {\n"
|
||||
" if (!(milliseconds is Num)) Fiber.abort(\"Milliseconds must be a number.\")\n"
|
||||
" if (milliseconds < 0) Fiber.abort(\"Milliseconds cannot be negative.\")\n"
|
||||
"\n"
|
||||
" startTimer_(milliseconds, Fiber.current)\n"
|
||||
"\n"
|
||||
" runNextScheduled_()\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" // TODO: Once the CLI modules are more fleshed out, find a better place to\n"
|
||||
" // put this.\n"
|
||||
" static schedule(callable) {\n"
|
||||
" if (__scheduled == null) __scheduled = []\n"
|
||||
" __scheduled.add(Fiber.new {\n"
|
||||
" callable.call()\n"
|
||||
" runNextScheduled_()\n"
|
||||
" })\n"
|
||||
" Scheduler.runNextScheduled_()\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" foreign static startTimer_(milliseconds, fiber)\n"
|
||||
"\n"
|
||||
" // Called by native code.\n"
|
||||
" static resumeTimer_(fiber) {\n"
|
||||
" fiber.transfer()\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" static runNextScheduled_() {\n"
|
||||
" if (__scheduled == null || __scheduled.isEmpty) {\n"
|
||||
" Fiber.suspend()\n"
|
||||
" } else {\n"
|
||||
" __scheduled.removeAt(0).transfer()\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
|
||||
Reference in New Issue
Block a user